ZJOI2007棋盘制作[动规 悬线法]
Posted lxyyyy
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了ZJOI2007棋盘制作[动规 悬线法]相关的知识,希望对你有一定的参考价值。
悬线法
H[i,j]为点(i,j)对应的悬线的长度
L[i,j]为点(i,j)对应的悬线向左最多能够移动到的位置。
R[i,j]为点(i,j)对应的悬线向右最多能够移动到的位置。
预处理:对于第i行 若(i,j)和(i,j-1)不同色则L[i,j]=L[i,j-1] R[i,j-1]=R[i,j]
若点(i,j)和点(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])
#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define rg register
#define Max(x,y) ((x)>(y)?(x):(y))
#define Min(x,y) ((x)>(y)?(y):(x))
const int N=2000+5,M=2e5+5,inf=0x3f3f3f3f,P=19650827;
int n,m,ans1,ans2,mp[N][N],l[N][N],r[N][N],h[N][N];
template <class t>void rd(t &x)
x=0;int w=0;char ch=0;
while(!isdigit(ch)) w|=ch=='-',ch=getchar();
while(isdigit(ch)) x=(x<<1)+(x<<3)+(ch^48),ch=getchar();
x=w?-x:x;
int main()
freopen("in2.txt","r",stdin);
//freopen("xor.out","w",stdout);
rd(n),rd(m);
for(int i=1;i<=n;++i)
for(int j=1;j<=m;++j) rd(mp[i][j]),l[i][j]=r[i][j]=j,h[i][j]=1;
for(int i=1;i<=n;++i)
for(int j=2;j<=m;++j) if(mp[i][j]^mp[i][j-1]) l[i][j]=l[i][j-1];
for(int j=m;j>=2;--j) if(mp[i][j]^mp[i][j-1]) r[i][j-1]=r[i][j];
for(int i=1;i<=n;++i)
for(int j=1;j<=m;++j)
if(i>1&&(mp[i][j]^mp[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]),h[i][j]=h[i-1][j]+1;
int x=r[i][j]-l[i][j]+1,y=Min(x,h[i][j]);
ans1=Max(ans1,y*y),ans2=Max(ans2,x*h[i][j]);
printf("%d\n%d\n",ans1,ans2);
return 0;
以上是关于ZJOI2007棋盘制作[动规 悬线法]的主要内容,如果未能解决你的问题,请参考以下文章