方法:悬线法
用途:解决矩形内满足要求的最优(最大)矩形的问题
实现方法:用一条线(横竖都行)不断向左右移动知道不满足约束或者到了边界为止
本题用l[i][j]表示(i,j)可以扩展的最左边的位置,r[i][j]表示可以扩展的最右边的位置,len[i][j]表示向上扩展的最长长度。
1 #include<stdio.h>
2 #define it register int
3 #define il inline
4 const int N=2005;
5 int l[N][N],r[N][N],a[N][N],len[N][N],n,m,ans1,ans2;
6 il int Min(it p,it q){
7 return p<q?p:q;
8 }
9 il int Max(it p,it q){
10 return p>q?p:q;
11 }
12 il void fr(int &num){
13 num=0;char c=getchar();int p=1;
14 while(c<'0'||c>'9') c=='-'?p=-1,c=getchar():c=getchar();
15 while(c>='0'&&c<='9') num=num*10+c-'0',c=getchar();
16 num*=p;
17 }
18 int main(){
19 fr(n),fr(m);
20 for(it i=1;i<=n;++i)
21 for(it j=1;j<=m;++j)
22 fr(a[i][j]),l[i][j]=r[i][j]=j,len[i][j]=1;
23 for(it i=1;i<=n;++i)
24 for(it j=2;j<=m;++j)
25 if(a[i][j]!=a[i][j-1]) l[i][j]=l[i][j-1];
26 for(it i=1;i<=n;++i)
27 for(it j=m-1;j;--j)
28 if(a[i][j]!=a[i][j+1]) r[i][j]=r[i][j+1];
29 //记录(i,j)可以向左右扩展的位置
30 for(it i=1,l1,r1;i<=n;++i)
31 for(it j=1;j<=m;++j){
32 if(i>1&&a[i][j]!=a[i-1][j]) l[i][j]=Max(l[i][j],l[i-1][j]),r[i][j]=Min(r[i][j],r[i-1][j]),len[i][j]=len[i-1][j]+1; //每次向上一层更新
33 l1=r[i][j]-l[i][j]+1,r1=Min(l1,len[i][j]),ans1=Max(ans1,r1*r1),ans2=Max(ans2,len[i][j]*l1); //更新答案
34 }
35 printf("%d
%d
",ans1,ans2);
36 return 0;
37 }