题目
传送门:QWQ
分析
先把题目给出的矩阵变换一下,如果$ a[i][j] $中$ i+j mod 2 = 1 $那么就对$ a[i][j] $取一下反。
接着就是求原图中最大的0、1子矩阵
详见lrj蓝书,悬线法维护最大0、1子矩阵。
代码
1 #include<bits/stdc++.h> 2 #define left lft 3 #define right rght 4 using namespace std; 5 const int maxn=2000; 6 int left[maxn][maxn], right[maxn][maxn], up[maxn][maxn] ; 7 int mp[maxn][maxn]; 8 int sqr(int x){return x*x;} 9 int main(){ 10 int n,m;scanf("%d%d",&n,&m); 11 for(int i=1;i<=n;i++) 12 for(int j=1;j<=m;j++){ 13 scanf("%d",&mp[i][j]); if((i+j)%2) mp[i][j]^=1; 14 } 15 int ans1=0,ans2=0; 16 for(int i=0;i<=m;i++) right[0][i]=1e9; 17 for(int i=1;i<=n;i++){ 18 left[i][1]=0; right[i][m]=m; 19 int le=0,ri=m+1; 20 for(int j=1;j<=m;j++){ 21 if(mp[i][j]){ 22 up[i][j]=up[i-1][j]+1; left[i][j]=max(left[i-1][j],le+1); 23 24 } 25 else{ le=j; } 26 } 27 28 for(int j=m;j>=1;j--){ 29 if(mp[i][j]){ 30 right[i][j]=min(ri-1,right[i-1][j]); 31 int linelen=right[i][j]-left[i][j]+1 ,rowlen=up[i][j]; 32 ans1=max(ans1,sqr(min(linelen,rowlen))); 33 ans2=max(ans2,linelen*rowlen); 34 } 35 else{ 36 ri=j; right[i][j]=m; 37 } 38 } 39 } 40 41 memset(right,0,sizeof(right)); memset(left,0,sizeof(left)); memset(up,0,sizeof(up)); 42 for(int i=0;i<=m;i++) right[0][i]=1e9; 43 for(int i=1;i<=n;i++){ 44 left[i][1]=0; right[i][m]=m; 45 int le=0,ri=m+1; 46 for(int j=1;j<=m;j++){ 47 if(!mp[i][j]){ 48 up[i][j]=up[i-1][j]+1; left[i][j]=max(left[i-1][j],le+1); 49 50 } 51 else{ le=j; } 52 } 53 54 for(int j=m;j>=1;j--){ 55 if(!mp[i][j]){ 56 right[i][j]=min(ri-1,right[i-1][j]); 57 int linelen=right[i][j]-left[i][j]+1 ,rowlen=up[i][j]; 58 ans1=max(ans1,sqr(min(linelen,rowlen))); 59 ans2=max(ans2,linelen*rowlen); 60 } 61 else{ 62 ri=j; right[i][j]=m; 63 } 64 } 65 } 66 printf("%d %d",ans1,ans2); 67 68 return 0; 69 }