题目传送门
这个东西叫悬线法
解法:
又是学肉dalao做题系列。
悬线法太强啦orz。。
就是预处理出每个位置向左向右延伸的最大长度。
l[i][j]表示向左,r[i][j]表示向右。
u[i][j]表示向上。
sum[i][j][0]表示i这条悬线上向左延伸的最大长度。因为是矩形所以我们要维护的是悬线上最小的那个。
sum[i][j][1]表示往右,同理。
然后知道sum[i][j]和u[i][j]就相当于知道了矩形的长和宽呗。
代码实现:
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<iostream>
#include<algorithm>
using namespace std;
int map[2100][2100],l[2100][2100],r[2100][2100],u[2100][2100];
int sum[2100][2100][2];
int main() {
int n,m;scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++)for(int j=1;j<=m;j++)scanf("%d",&map[i][j]);
for(int i=1;i<=n;i++)for(int j=2;j<=m;j++)
l[i][j]=map[i][j]!=map[i][j-1]?l[i][j-1]+1:0;
for(int i=1;i<=n;i++)for(int j=m-1;j>=1;j--)
r[i][j]=map[i][j]!=map[i][j+1]?r[i][j+1]+1:0;
int ans=0;
for(int i=1;i<=n;i++)for(int j=1;j<=m;j++) {
if(i==1) {sum[i][j][0]=l[i][j];sum[i][j][1]=r[i][j];continue;}
if(map[i][j]!=map[i-1][j]) {
u[i][j]=u[i-1][j]+1;
sum[i][j][0]=min(sum[i-1][j][0],l[i][j]);sum[i][j][1]=min(sum[i-1][j][1],r[i][j]);
}else {
sum[i][j][0]=l[i][j];sum[i][j][1]=r[i][j];
}ans=max(ans,(sum[i][j][0]+sum[i][j][1]+1)*(u[i][j]+1));
}int ans1=0;
for(int i=1;i<=n;i++)for(int j=1;j<=m;j++) {
int len=min(sum[i][j][0]+sum[i][j][1]+1,u[i][j]+1);ans1=max(ans1,len*len);
}printf("%d\n",ans1);printf("%d\n",ans);
return 0;
}