[悬线法] BZOJ1057 [ZJOI2007]棋盘制作

当年是怎么把这道悬线法SB题漏掉没刷的

总之悬线法,刚好在省选前复习下

一开始愣是没看出来 诶 太弱

#include<cstdio>
#include<cstdlib>
#include<algorithm>
using namespace std;

inline char nc()
{
	static char buf[100000],*p1=buf,*p2=buf;
	if (p1==p2) { p2=(p1=buf)+fread(buf,1,100000,stdin); if (p1==p2) return EOF; }
	return *p1++;
}

inline void read(int &x)
{
	char c=nc(),b=1;
	for (;!(c>='0' && c<='9');c=nc()) if (c=='-') b=-1;
	for (x=0;c>='0' && c<='9';x=x*10+c-'0',c=nc()); x*=b;
}

inline int sqr(int x){
	return x*x;
}

int n,m;
int M[2005][2005];
int left[2005][2005],right[2005][2005],height[2005][2005];

int main()
{
	freopen("t.in","r",stdin);
	freopen("t.out","w",stdout);
	read(n); read(m);
	for (int i=1;i<=n;i++)
		for (int j=1;j<=m;j++)
			read(M[i][j]);
	for (int i=1;i<=n;i++)
	{
		int l=1,r=1;
		while (l<=m)
		{
			while (r+1<=m && M[i][r]==M[i][r+1]^1) r++;
			for (int j=l;j<=r;j++)
				left[i][j]=l,right[i][j]=r;
			l=r=r+1;
		}
	}
	for (int j=1;j<=m;j++)
		left[0][j]=1,right[0][j]=m;
	for (int i=1;i<=n;i++)
		for (int j=1;j<=m;j++)
			if (i==1 || M[i][j]==M[i-1][j]^1)
			{
				height[i][j]=height[i-1][j]+1;
				left[i][j]=max(left[i][j],left[i-1][j]);
				right[i][j]=min(right[i][j],right[i-1][j]);
			}
			else 
				height[i][j]=1;
	int ans1=0,ans2=0;
	for (int i=1;i<=n;i++)
		for (int j=1;j<=m;j++)
		{
			ans1=max(ans1,height[i][j]*(right[i][j]-left[i][j]+1));
			ans2=max(ans2,sqr(min(height[i][j],(right[i][j]-left[i][j]+1))));
		}
	printf("%d\n%d\n",ans2,ans1);
	return 0;		
}


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