传送门
设h(i,j)表示以(i,j)为下端点的悬线的最长长度,l(i,j)和r(i,j)分别表示使悬线有此长度的左边最近的限制和右边最近的限制。
预处理L(i,j)R(i,j)分别表示点(i,j)能扩展到的最近的不合法点。
如果(i,j)与(i-1,j)颜色相同,那么h(i,j)=1,l(i,j)=L(i,j),r(i,j)=R(i,,j);
如果(i,j)与(i-1,j)颜色不相同,那么h(i,j)=h(i-1,j)+1,l(i,j)=max(l(i-1,j),L(i,j)),r(i,j)=min(r(i-1,j),R(i,j)).
矩形的答案即为max(h(i,j)*(r(ii,j)-l(i,j)-1)),正方形需要把长宽取一下min
#include
#include
#include
using namespace std;
#define N 2005
int n,m,ans1,ans2;
int a[N][N],L[N][N],R[N][N],l[N][N],r[N][N],h[N][N];
int main()
{
scanf("%d%d",&n,&m);
for (int i=1;i<=n;++i)
for (int j=1;j<=m;++j)
scanf("%d",&a[i][j]);
for (int i=1;i<=n;++i)
{
L[i][1]=0;
for (int j=2;j<=m;++j)
if (a[i][j]!=a[i][j-1]) L[i][j]=L[i][j-1];
else L[i][j]=j-1;
R[i][m]=m+1;
for (int j=m-1;j>=1;--j)
if (a[i][j]!=a[i][j+1]) R[i][j]=R[i][j+1];
else R[i][j]=j+1;
}
for (int i=1;i<=m;++i) h[1][i]=1,l[1][i]=L[1][i],r[1][i]=R[1][i];
for (int i=2;i<=n;++i)
{
for (int j=1;j<=m;++j)
if (a[i][j]==a[i-1][j])
{
h[i][j]=1;
l[i][j]=L[i][j],r[i][j]=R[i][j];
}
else
{
h[i][j]=h[i-1][j]+1;
l[i][j]=max(l[i-1][j],L[i][j]);
r[i][j]=min(r[i-1][j],R[i][j]);
}
}
for (int i=1;i<=n;++i)
for (int j=1;j<=m;++j)
{
int len=min(h[i][j],r[i][j]-l[i][j]-1);
if (len>0) ans1=max(ans1,len*len);
ans2=max(ans2,h[i][j]*(r[i][j]-l[i][j]-1));
}
printf("%d\n%d\n",ans1,ans2);
}