您的位置:首页 > 其它

[BZOJ]1057: [ZJOI2007]棋盘制作

2017-03-14 08:31 411 查看
FallDream dalao随手切 赶紧上他博客抄学习了一个。

题目大意:给出一个n*m的01矩阵,求最大的子正方形/矩形,满足任意相邻格子不同。(n,m<=2000)

思路:把行列坐标相加为偶数的异或上1,题目变成求最大的全为0或1的子正方形/矩形,我们分别处理,预处理出每个格子向右有多少连续的0/1,枚举列,用个单调栈维护和统计答案(维护上升序列),复杂度O(nm)。

#include<cstdio>
#include<algorithm>
using namespace std;
inline int read()
{
int x;char c;
while((c=getchar())<'0'||c>'9');
for(x=c-'0';(c=getchar())>='0'&&c<='9';)x=(x<<3)+(x<<1)+c-'0';
return x;
}
#define MN 2000
int n,m,a[MN+5][MN+5],f[MN+5][MN+5],ans1,ans2,q[MN+5],qx[MN+5],qn;
inline int sqr(int x){return x*x;}
void solve(int x)
{
int i,j;
for(i=1;i<=n;++i)for(j=m;j;--j)f[i][j]=a[i][j]==x?f[i][j+1]+1:0;
for(i=1;i<=m;++i)for(j=qn=0;j++<=n;qx[++qn]=f[j][i])
for(q[qn+1]=j;qn&&f[j][i]<qx[qn];--qn)
ans1=max(ans1,sqr(min(j-q[qn],qx[qn]))),
ans2=max(ans2,(j-q[qn])*qx[qn]);
}
int main()
{
n=read();m=read();
for(int i=1;i<=n;++i)for(int j=1;j<=m;++j)a[i][j]=read()^((i+j)&1);
solve(0);solve(1);
printf("%d\n%d",ans1,ans2);
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: