题意
给出一个01矩阵,可以将任意行任意列取反,问最大全1子矩形的面积是多少。
n,m<=2000
分析
有一个结论就是,若一个子矩形S中的任意一个2*2的子矩形都含有偶数个1,则存在一种操作使得S中全为1。
证明:
若S中一个2*2的子矩形中有奇数个1,则无论怎么操作,该子矩形中仍然有奇数个1,所以必然不满足。
若我们让S的第一行和第一列全都是1,通过归纳法不难发现S的每一个位置都必然为1。
然后就可以随便做了。
代码
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<algorithm>
using namespace std;
const int N=2005;
const int inf=1000000000;
int n,m,lef[N][N],rig[N][N],up[N][N];
bool ma[N][N];
char str[N];
int main()
{
scanf("%d%d",&n,&m);
for (int i=1;i<=n;i++)
{
scanf("%s",str+1);
for (int j=1;j<=m;j++) ma[i][j]=str[j]=='#'?1:0;
}
for (int i=1;i<n;i++)
for (int j=1;j<m;j++)
ma[i][j]=ma[i][j]^ma[i][j+1]^ma[i+1][j]^ma[i+1][j+1];
n--;m--;
for (int i=1;i<=n;i++)
{
for (int j=1;j<=m;j++) lef[i][j]=ma[i][j]?0:lef[i][j-1]+1;
for (int j=m;j>=1;j--) rig[i][j]=ma[i][j]?0:rig[i][j+1]+1;
}
for (int i=1;i<=m;i++) lef[0][i]=rig[0][i]=inf;
int ans=max(n+1,m+1);
for (int i=1;i<=n;i++)
for (int j=1;j<=m;j++)
{
if (ma[i][j]) up[i][j]=0,lef[i][j]=rig[i][j]=inf;
else
{
up[i][j]=up[i-1][j]+1;
lef[i][j]=min(lef[i][j],lef[i-1][j]);
rig[i][j]=min(rig[i][j],rig[i-1][j]);
ans=max(ans,(up[i][j]+1)*(lef[i][j]+rig[i][j]));
}
}
printf("%d",ans);
return 0;
}