A.All-one Matrices(单调栈)
•题意
给你一个只包含 0,1 的 n×m 的矩阵 s;
求只由 1 组成的矩阵的个数,并且这些矩阵不存在包含关系;
•题解
定义 h[ i ][ j ] 表示 ( i , j ) 位置及其之上的连续的 1 的个数;
那么,通过单调栈可以求出 ( i , j ) 位置的 l = L[ i ][ j ] 和 r = R[ i ][ j ];
当前这个只包含 1 的矩阵是否包含于其他更大的矩阵呢?
即如何判断当前这个矩阵对答案的贡献呢?
只需要判断 i+1 行的 [ l , r ] 列是否含有 r-l+1 个 1 即可;
如果 i+1 行的相应列含有 r-l+1 个 1,那么,由下一行的相同列组成的 1 矩阵势必要包含当前的矩阵;
如果当前矩阵对答案有贡献,是不是就让 ans++ 呢?
答案是否定的;
因为如果 ( i , j ) 位置之前的位置 ( i , x )(x < j) 的高度 h[ i ][ x ] 与 h[ i ][ j ] 相等的;
并且和 h[ i ][ j ] 所求的 1 矩阵相同,那么,当前这个矩阵就不能对答案有贡献;
这个通过单调栈求出的信息判断一下就好了;
•Code
View Code1 #include<bits/stdc++.h> 2 using namespace std; 3 #define INF 0x3f3f3f3f 4 #define INFll 0x3f3f3f3f3f3f3f3f 5 #define ll long long 6 #define pii pair<int ,int > 7 #define psi pair<string ,int > 8 #define pb(x) push_back(x) 9 #define ls(x) (x<<1) 10 #define rs(x) (x<<1|1) 11 #define GCD(a,b) __gcd(a,b) 12 #define PI acos(-1) 13 #define mem(a,b) memset(a,b,sizeof(a)) 14 #define endl '\n' 15 #define isLeap(x) (x%4==0&&x%100!=0||x%400==0) 16 #define Close() std::ios::sync_with_stdio(false);cin.tie(0);cout.tie(0); 17 const int maxn=3e3+50; 18 19 int n,m; 20 char s[maxn][maxn]; 21 int h[maxn]; 22 int l[maxn]; 23 int r[maxn]; 24 int one[maxn]; 25 stack<int >sta; 26 vector<int >v[maxn]; 27 28 void Clear() 29 { 30 while(!sta.empty()) 31 sta.pop(); 32 } 33 void Work() 34 { 35 Clear(); 36 for(int i=1;i <= m;++i) 37 { 38 while(!sta.empty() && h[sta.top()] >= h[i]) 39 sta.pop(); 40 41 l[i]=sta.empty() ? 1:sta.top()+1; 42 sta.push(i); 43 } 44 Clear(); 45 for(int i=m;i >= 1;--i) 46 { 47 while(!sta.empty() && h[sta.top()] >= h[i]) 48 sta.pop(); 49 50 r[i]=sta.empty() ? m:sta.top()-1; 51 sta.push(i); 52 } 53 } 54 ll Solve() 55 { 56 mem(h,0); 57 58 ll ans=0; 59 for(int i=1;i <= n;++i) 60 { 61 for(int j=1;j <= m;++j) 62 { 63 if(s[i][j] == '1') 64 h[j]++; 65 else 66 h[j]=0; 67 } 68 69 Work();///单调栈 70 71 mem(one,0); 72 if(i != n) 73 { 74 for(int j=1;j <= m;++j) 75 one[j]=one[j-1]+(s[i+1][j] == '1'); 76 } 77 for(int j=0;j <= n;++j) 78 v[j].clear(); 79 80 for(int j=1;j <= m;++j) 81 { 82 int siz=v[h[j]].size(); 83 int cur=h[j]; 84 ///如果其前一个高度相同的位置与当前位置j的l[j],r[j]相同,那么当前位置无需计算 85 if(cur == 0 || siz != 0 && l[v[cur][siz-1]] == l[j] && r[v[cur][siz-1]] == r[j]) 86 continue; 87 88 int x=l[j]; 89 int y=r[j]; 90 v[h[j]].push_back(j); 91 92 if(one[y]-one[x-1] != y-x+1) 93 ans++;///如果i+1行的[x,y]列无y-x+1个1,那么ans++ 94 } 95 } 96 return ans; 97 } 98 int main() 99 { 100 // freopen("C:\\Users\\hyacinthLJP\\Desktop\\in&&out\\contest","r",stdin); 101 // freopen("C:\\Users\\hyacinthLJP\\Desktop\\in&&out\\contest","w",stdout); 102 scanf("%d%d",&n,&m); 103 for(int i=1;i <= n;++i) 104 scanf("%s",s[i]+1); 105 106 printf("%lld\n",Solve()); 107 108 return 0; 109 }