在做本题之前, 我们先要接触一个东西叫悬线法
在悬线法中, 我们定义
表示 能够向左延伸的最远位置(就是记录的能够走的,最左边的纵坐标)
表示 能够向右延伸的最远位置(就是记录的能够走的,最右边的纵坐标)
表示 能够向上延伸的最大距离
#include<bits/stdc++.h>
using namespace std;
int n, m;
int g[2010][2010], l[2010][2010], r[2010][2010], u[2010][2010];
int main()
{
ios::sync_with_stdio(false),cin.tie(0),cout.tie(0);
cin >> n >> m;
for(int i = 1; i <= n; i ++ )
for(int j = 1; j <= m; j ++ )
{
cin >> g[i][j];
l[i][j] = r[i][j] = j; //初始化为当前位置
u[i][j] = 1; //初始化距离为 1
}
for(int i = 1; i <= n; i ++ )
for(int j = 2; j <= m; j ++ )
{
if(g[i][j] != g[i][j - 1])
l[i][j] = l[i][j - 1]; //如果能够向左扩展
}
for(int i = 1; i <= n; i ++ )
for(int j = m - 1; j >= 1; j -- )
{
if(g[i][j] != g[i][j + 1]) //如果能够向右扩展
r[i][j] = r[i][j + 1];
}
int s = 1, dist = 1;
for(int i = 1; i <= n; i ++ ) //枚举端点
for(int j = 1; j <= m; j ++ )
{
if(g[i][j] != g[i - 1][j] && i != 1) //如果能够向上扩展, i != 1是因为1不能向上扩展了
{
u[i][j] = u[i - 1][j] + 1;
l[i][j] = max(l[i][j], l[i - 1][j]); //记录最右边的位置
r[i][j] = min(r[i][j], r[i - 1][j]); //记录最左边的位置
}
dist = max(dist, min(u[i][j], r[i][j] - l[i][j] + 1)); //正方形
s = max(s, u[i][j] * (r[i][j] - l[i][j] + 1)); //矩形
}
cout << dist * dist << '\n';
cout << s << '\n';
}