BZOJ1057: [ZJOI2007]棋盘制作

悬线法DP
根据前者推的最远处开始算
可以证明是n*m的

#include<cstdio>
#include<iostream>
#include<cstring>
using namespace std;
char c;
bool flag;
inline void read(int &a)
{
 a=0;do c=getchar();while(c!='-'&&(c<'0'||c>'9'));
 if(c=='-')c=getchar(),flag=true;
 while(c<='9'&&c>='0')a=(a<<3)+(a<<1)+c-'0',c=getchar();
 if(flag)flag=false,a=-a;
}
int n,m,i,j,t,ans1,ans2;
int mp[2005][2005],h[2005][2005],l[2005][2005],r[2005][2005];
int main()
{
 read(n),read(m);
 for(i=1;i<=n;i++)
 for(j=1;j<=m;j++)
 {
 read(mp[i][j]);
 if(i==1)h[i][j]=1;
 else if(mp[i][j]!=mp[i-1][j])h[i][j]=h[i-1][j]+1;
 else h[i][j]=1;
 }
 for(i=1;i<=n;i++)
 {
 for(j=1;j<=m;j++)
 {
 l[i][j]=j;
 while(l[i][j]>1&&h[i][l[i][j]-1]>=h[i][j]&&mp[i][l[i][j]-1]!=mp[i][l[i][j]]) 
 l[i][j]=l[i][l[i][j]-1];
 }
 for(j=m;j;j--)
 {
 r[i][j]=j;
 while(r[i][j]<m&&h[i][r[i][j]+1]>=h[i][j]&&mp[i][r[i][j]+1]!=mp[i][r[i][j]]) 
 r[i][j]=r[i][r[i][j]+1];
 }
 for(int j=1;j<=m;j++)
 {
 t=r[i][j]-l[i][j]+1;
 ans2=max(ans2,t*h[i][j]);
 t=min(t,h[i][j]);
 ans1=max(ans1,t*t);
 }
 }
 printf("%d\n%d\n",ans1,ans2);
 return 0;
}

你可能感兴趣的:(BZOJ1057: [ZJOI2007]棋盘制作)