題目連接:https://ac.nowcoder.com/acm/contest/882/Hspa
題目:給n×m的由01組成的矩陣,求次大全1子矩陣的大小。code
思路:第一步仍是降維操做,用a[i][j]記錄以第i行爲底的全1直方圖的高,如對於矩陣:blog
1111 0101 1100 1111
其矩陣a爲:it
1111 0202 1300 2411
以後對於每一行的全部列用單調棧維護每一個數左/右邊第一個比它小的值的下標,則以a[i][j]爲高的矩陣最大爲(r[j]-l[j]+1)×a[i][j],而後維護更新max1,max2便可。io
須要注意的是,max1維護最大矩陣的大小,max2維護次大矩陣的大小,mx、my維護最大矩陣的右下角下標,xx、yy維護最大矩陣的長和寬,若當前面積值>=max1,須要比較是不是同一個矩陣(by mx、my、xx、yy是否相等來比較),如果,則不能更新max2=max1,不然,即不是一個矩陣,則能夠max2=max1.class
AC代碼:test
#include<cstdio> #include<algorithm> using namespace std; int n,m,p1,p2,max1,max2; int a[1005][1005],stk1[1005],stk2[1005]; int l[1005],r[1005]; char s[1005]; int mx,my,xx,yy; int main(){ scanf("%d%d",&n,&m); for(int i=1;i<=n;++i){ a[i][0]=-1,a[i][m+1]=-1; scanf("%s",s); for(int j=1;j<=m;++j){ int tmp=s[j-1]-'0'; if(tmp) a[i][j]=a[i-1][j]+1; } } stk1[0]=0,stk2[0]=m+1; for(int i=1;i<=n;++i){ p1=p2=1; for(int j=1;j<=m;++j){ while(a[i][stk1[p1-1]]>=a[i][j]) --p1; l[j]=stk1[p1-1]; stk1[p1++]=j; } for(int j=m;j>=1;--j){ while(a[i][stk2[p2-1]]>=a[i][j]) --p2; r[j]=stk2[p2-1]; stk2[p2++]=j; } for(int j=1;j<=m;++j){ int x=r[j]-l[j]-1,y=a[i][j]; if(!y) continue; int aa=i,bb=r[j]-1; if(x*y>=max1){ if(!(aa==mx&&bb==my&&x==xx&&y==yy)) max2=max1; max1=x*y,mx=aa,my=bb,xx=x,yy=y; } else if(x*y>max2) max2=x*y; max2=max(max2,max((x-1)*y,x*(y-1))); } } printf("%d\n",max2); return 0; }