2019牛客多校第二场H题(悬线法)
把以前的题补补,用悬线求面积第二大的子矩形。我们先求出最大子矩阵的面积,并记录其行三个方向上的悬线长度。然后排除这个矩形,记得还得特判少一行或者少一列的情况
#include <bits/stdc++.h> using namespace std; const int maxn=1e3+10; int n; int mat[maxn][maxn],Left[maxn][maxn],Right[maxn][maxn],up[maxn][maxn]; int main() { int T; T=1; while(T--) { int m,n; cin>>m>>n; for(int i=0;i<m;i++) { for(int j=0;j<n;j++) { char ch; cin>>ch; mat[i][j]=ch=='1'?0:1; } } int ans=0,max2=0,l,r,u,b; for(int i=0;i<m;i++) { int lo=-1,ro=n; for(int j=0;j<n;j++) { if(mat[i][j]==1) { up[i][j]=Left[i][j]=0;lo=j; } else { up[i][j]=i==0?1:up[i-1][j]+1; Left[i][j]=i==0?lo+1:max(Left[i-1][j],lo+1); } } for(int j=n-1;j>=0;j--) { if(mat[i][j]==1) { Right[i][j]=n;ro=j; } else { Right[i][j]=i==0?ro-1:min(Right[i-1][j],ro-1); if(ans<(up[i][j]*(Right[i][j]-Left[i][j]+1))) { ans=up[i][j]*(Right[i][j]-Left[i][j]+1); u=up[i][j],l=Left[i][j],r=Right[i][j],b=i; } } } } max2=max(max2,u*(r-l)); max2=max(max2,(u-1)*(r-l+1)); for(int i=0;i<m;i++) { int lo=-1,ro=n; for(int j=0;j<n;j++) { if(mat[i][j]==1) { up[i][j]=Left[i][j]=0;lo=j; } else { up[i][j]=i==0?1:up[i-1][j]+1; Left[i][j]=i==0?lo+1:max(Left[i-1][j],lo+1); } } for(int j=n-1;j>=0;j--) { if(mat[i][j]==1) { Right[i][j]=n;ro=j; } else { Right[i][j]=i==0?ro-1:min(Right[i-1][j],ro-1); if(u==up[i][j]&&l==Left[i][j]&&r==Right[i][j]&&b==i) continue; if(max2<(up[i][j]*(Right[i][j]-Left[i][j]+1))) { max2=up[i][j]*(Right[i][j]-Left[i][j]+1); } } } } cout<<max2<<"\n"; } return 0; }