悬线法。
传送门:GO
设l[i][j],r[i][j],up[i][j]表示能向左延伸的最远位置,向右延伸的最远位置,上方的最长距离。
预处理一下l和r,n方更新即可。
其余很好懂,看代码吧。
1 #include<bits/stdc++.h> 2 using namespace std; 3 int read(){ 4 int x=0,f=1; 5 char c=getchar(); 6 while(!isdigit(c)){ 7 if(c=='-') f=-1; 8 c=getchar(); 9 } 10 while(isdigit(c)){ 11 x=x*10+c-'0'; 12 c=getchar(); 13 } 14 return x*f; 15 } 16 const int N=2010; 17 int n,m,ans1,ans2,c,d; 18 bool a[N][N]; 19 int l[N][N],r[N][N],up[N][N]; 20 int main(){ 21 n=read();m=read(); 22 for(int i=1;i<=n;i++){ 23 for(int j=1;j<=m;j++){ 24 a[i][j]=read(); 25 l[i][j]=r[i][j]=j; 26 up[i][j]=1; 27 } 28 } 29 for(int i=1;i<=n;i++){ 30 for(int j=2;j<=m;j++){ 31 if(a[i][j]!=a[i][j-1]) l[i][j]=l[i][j-1]; 32 } 33 for(int j=m-1;j>=1;j--){ 34 if(a[i][j]!=a[i][j+1]) r[i][j]=r[i][j+1]; 35 } 36 } 37 for(int i=1;i<=n;i++){ 38 for(int j=1;j<=m;j++){ 39 if(a[i][j]!=a[i-1][j]&&i>1){ 40 l[i][j]=max(l[i][j],l[i-1][j]); 41 r[i][j]=min(r[i][j],r[i-1][j]); 42 up[i][j]=up[i-1][j]+1; 43 } 44 c=r[i][j]-l[i][j]+1; 45 d=min(c,up[i][j]); 46 ans1=max(d*d,ans1); 47 ans2=max(c*up[i][j],ans2); 48 } 49 } 50 printf("%d %d",ans1,ans2); 51 return 0; 52 }