这个题也很奇妙,也是在一个简单模型上面做一点点更改,然后就可以得出答案,算一道很妙的题目了,个人觉得应该是铜牌把关题的那种,如果做得快的话说不定能拿银牌
显然我们得遍历所有矩阵,但是这个矩阵可以有奇妙的方法遍历,我们可以利用信息保存,减少一些不必要的运算来保存。然后得出答案。
下面就是我们通过枚举下届,然后通过这个下届我们先缓存一下高度,对这个高度进行操作。
这个过程我们可以通过单调栈来处理,单调栈本身就是用来处理一些矩形的面积,计数的东东,在它的运行过程它会把当前高度的最大面积都计算出来,这个自然是最妙的。。。。。。。。。这个可以保证当前是对的
那我们怎么能保证下面是对的呢,如果下面不是满的1的话那么这就是唯一的,这个应该是挺好想的。
然后考虑如果高度相同,显然只有一个计数,这时候应当把这个也考虑进去,这个相同高度取最大就ok
下面是代码:
1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 #include <algorithm> 5 #include <queue> 6 #include <stack> 7 #include <cmath> 8 typedef long long ll; 9 using namespace std; 10 const int maxn=3100; 11 int n,m; 12 char s[maxn][maxn]; 13 int hi[maxn][maxn]; 14 int sum[maxn][maxn]; 15 int ai[maxn],siz[maxn]; 16 int ans=0; 17 18 void solve(int k){ 19 stack<int> sta; sta.push(0); 20 for(int i=1;i<=m+1;i++){ 21 if(ai[i]>ai[sta.top()]){ 22 sta.push(i); 23 }else{ 24 int len=0; 25 while(!sta.empty()&&ai[i]<=ai[sta.top()]){ 26 if(ai[i]==ai[sta.top()]){ 27 len+=siz[sta.top()]; 28 sta.pop();continue; 29 } 30 len+=siz[sta.top()]; 31 int l=i-len,r=i-1; 32 if(sum[k+1][r]-sum[k+1][l-1]!=(r-l+1)){ 33 ans++; 34 } 35 sta.pop(); 36 } 37 sta.push(i);siz[i]=len+1; 38 } 39 } 40 } 41 42 43 int main(){ 44 scanf("%d%d",&n,&m); 45 for(int i=1;i<=n;i++) scanf("%s",s[i]+1); 46 for(int i=1;i<=n;i++){ 47 for(int j=1;j<=m;j++){ 48 hi[i][j]=s[i][j]=='1'?hi[i-1][j]+1:0; 49 sum[i][j]=sum[i][j-1]+(s[i][j]=='1'); 50 } 51 } 52 53 for(int i=1;i<=n;i++){ 54 for(int j=1;j<=m;j++) ai[j]=hi[i][j]; 55 for(int j=1;j<=m;j++) siz[j]=1; 56 ai[0]=0;ai[m+1]=0; 57 solve(i); 58 } 59 printf("%d ",ans); 60 return 0; 61 }