题目链接:https://ac.nowcoder.com/acm/contest/888/A
题目大意:问有多少个全1的子矩形,且该矩形不会被另外一个全1子矩形覆盖。
解题报告:
参考博客:https://blog.csdn.net/ccsu_cat/article/details/99087362
我们预处理每个1的高度以及每一行的前缀和,枚举每一行 i,单调栈求出每个点 j 以h[i][j](1的高度)为高度的矩形左边界L[j]和右边界R[j],然后枚举每个点,如果sum[i + 1][R[j]] - sum[i + 1][L[j] - 1] != R[j] - L[j] + 1,说明这个矩形下面一排不全是1,不会被覆盖,答案++,然后我们要去重,可能有多个点 j,他们形成的矩形是一模一样的,我们再用一个单调栈(维护单调递增的高度)去一下重,如果栈顶元素高度等于当前点高度,说明是重复的,不用计算。
AC代码:
1 #include<bits/stdc++.h> 2 #define numm ch-48 3 #define pd putchar(' ') 4 #define pn putchar(' ') 5 #define pb push_back 6 #define fi first 7 #define se second 8 #define fre1 freopen("1.txt","r",stdin) 9 #define fre2 freopen("2.txt","w",stdout) 10 #define debug cout<<"debug"<<endl 11 using namespace std; 12 template <typename T> 13 void read(T &res) { 14 bool flag=false;char ch; 15 while(!isdigit(ch=getchar())) (ch=='-')&&(flag=true); 16 for(res=numm;isdigit(ch=getchar());res=(res<<1)+(res<<3)+numm); 17 flag&&(res=-res); 18 } 19 template <typename T> 20 void write(T x) { 21 if(x<0) putchar('-'),x=-x; 22 if(x>9) write(x/10); 23 putchar(x%10+'0'); 24 } 25 typedef long long ll; 26 const int maxn=3010; 27 const int maxm=505; 28 const int mod=1e9+7; 29 int a[maxn][maxn]; 30 int sum[maxn][maxn]; ///每一行的前缀和 31 int h[maxn][maxn]; ///每一行每一列往上的最大高度 32 int L[maxn],R[maxn]; 33 ///L[j]:h[i][j]这个高度的矩形的左边界 34 ///R[j]:h[i][j]这个高度的矩形的右边界 35 int main() 36 { 37 // #define local 38 #ifdef local 39 fre1; 40 // fre2; 41 #endif // local 42 int n,m; 43 read(n),read(m); 44 for(int i=1;i<=n;i++) 45 for(int j=1;j<=m;j++) { 46 scanf("%1d",&a[i][j]); 47 if(a[i][j]) 48 h[i][j]=h[i-1][j]+1; 49 sum[i][j]=sum[i][j-1]+a[i][j]; 50 } 51 int ans=0; 52 for(int i=n;i;i--) { 53 stack<int>sta; 54 // while(!sta.empty()) sta.pop(); 55 sta.push(0); 56 for(int j=1;j<=m;j++) { 57 while(!sta.empty()&&h[i][j]<=h[i][sta.top()]) sta.pop(); 58 if(sta.empty()) L[j]=-1; ///此时h[i][j]=0 59 else L[j]=sta.top()+1; 60 sta.push(j); 61 } 62 while(!sta.empty()) sta.pop(); 63 sta.push(m+1); 64 for(int j=m;j;j--) { 65 while(!sta.empty()&&h[i][j]<=h[i][sta.top()]) sta.pop(); 66 if(sta.empty()) R[j]=-1; ///此时h[i][j]=0 67 else R[j]=sta.top()-1; 68 sta.push(j); 69 } 70 while(!sta.empty()) sta.pop(); 71 for(int j=1;j<=m;j++) { 72 if(!h[i][j]) { 73 while(!sta.empty()) sta.pop(); 74 continue; 75 } 76 while(!sta.empty()&&h[i][j]<h[i][sta.top()]) sta.pop(); 77 if(sta.empty()||h[i][j]!=h[i][sta.top()]) { 78 int l=L[j]; 79 int r=R[j]; 80 if(sum[i+1][r]-sum[i+1][l-1]!=r-l+1) ans++; 81 sta.push(j); 82 } 83 } 84 } 85 write(ans);pn; 86 return 0; 87 }