H题:https://ac.nowcoder.com/acm/contest/882/H
题意:给你一个n*m的01矩阵,要你求出这个01矩阵中第二大的全1子矩阵,如果没有第二大的矩形就输出0
(1): 这个题有一个很常见的模型的就是我们对每一行单独维护一个全一子矩阵,这样的话这道题就变成了一道模版题??????
(2): 一个很常见的模型这个可以通过单调栈预处理出来?
(3): 然后就很奇妙了,我们该怎么求出第二大了,他可以从那儿出来
(4): 对单调栈模型进行考虑,这个东西移动的时候保存的是以当前这个点的高度为高向左走的矩形的最大值。这样的话我们对单个最高的矩形保存一个最大的矩形就可
(5): 通过单调栈这样的处理的话,我们存下来的东西就是这个单调栈移动下来的以当前矩阵为高的最大矩形的值,但是这样的话我们对每一行每一列我们都只保存了最大值,而次大值我们都把他给舍弃了,这样是不好的。
(6): 而正是因为我们只保存了最大值,我们忽略了次大值的来源,所以我们这道题才会一直wa。
(7): 下面是代码:
1 #include<bits/stdc++.h> 2 using namespace std; 3 #define maxn 1005 4 char mp[maxn][maxn]; 5 int n,m,f[maxn][maxn],M1,M2; 6 7 int stk[maxn],top,w[maxn]; 8 void calc(int i){ 9 top=0; 10 f[i][m+1]=0; 11 memset(w,0,sizeof w); 12 for(int j=1;j<=m+1;j++) 13 if(f[i][j]>stk[top]){ 14 stk[++top]=f[i][j]; 15 w[top]=1; 16 } 17 else { 18 int width=0; 19 while(f[i][j]<stk[top]){ 20 width+=w[top]; 21 22 if(stk[top]*(width)>=M1){ 23 M2=max(M1,stk[top]*(width-1)); 24 M1=stk[top]*(width); 25 } 26 else 27 M2=max(M2,stk[top]*width); 28 29 top--; 30 } 31 stk[++top]=f[i][j],w[top]=width+1; 32 } 33 } 34 35 int main(){ 36 cin>>n>>m; 37 for(int i=1;i<=n;i++)scanf("%s",mp[i]+1); 38 for(int i=1;i<=n;i++){ 39 for(int j=1;j<=m;j++) 40 if(mp[i][j]=='1') 41 f[i][j]=f[i-1][j]+1; 42 else f[i][j]=0; 43 } 44 for(int i=1;i<=n;i++) 45 calc(i); 46 cout<<M2<<endl; 47 }