题面:
题解:
了解悬线法的使用。
代码:
//悬线法
//好久之前就看到这个东西了,但是一直没写过题目
//解决给定矩阵中满足条件的最大子矩阵
//用一条线(横竖貌似都行)左右移动直到不满足约束条件或者到达边界
//left[i][j]代表从(i,j)能到达的最左位置
//right[i][j]代表从(i,j)能到达的最右位置
//up[i][j]代表从(i,j)向上扩展最长长度.
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<string>
#include<cmath>
#include<queue>
#include<vector>
#define ll long long
using namespace std;
const int maxn=2100;
int l[maxn][maxn],r[maxn][maxn],up[maxn][maxn];
int a[maxn][maxn];
int ans1,ans2;
int main(void)
{
int n,m;
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++)
{
for(int j=1;j<=m;j++)
{
scanf("%d",&a[i][j]);
l[i][j]=r[i][j]=j;
up[i][j]=1;
}
}
for(int i=1;i<=n;i++)
{
for(int j=2;j<=m;j++)
if(a[i][j]!=a[i][j-1])
l[i][j]=l[i][j-1];
for(int j=m-1;j>=1;j--)
if(a[i][j]!=a[i][j+1])
r[i][j]=r[i][j+1];
}
for(int i=1;i<=n;i++)
{
for(int j=1;j<=m;j++)
{
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]);
up[i][j]=up[i-1][j]+1;
}
int cl=r[i][j]-l[i][j]+1;
int ml=min(cl,up[i][j]);
ans1=max(ans1,ml*ml);
ans2=max(ans2,cl*up[i][j]);
}
}
printf("%d\n%d\n",ans1,ans2);
return 0;
}