【BZOJ1453】[Wc]Dface双面棋盘 线段树+并查集

【BZOJ1453】[Wc]Dface双面棋盘

Description

Input

Output

Sample Input


Sample Output


HINT

题解:话说看到题的第一反应其实是LCT。。。还是学学正解的写法吧(虽然复杂度不如LCT)。

我们用线段树维护所有的行,每个叶子节点都代表一个列,每个线段树的节点都维护如下信息:左面那列的连通情况(用并查集维护),右面那列的连通情况,左面那列的颜色,右面那列的颜色。合并的时候枚举中间的那列,如果相邻颜色相同则进行并查集合并。特别地,如果在合并后,一些点在并查集中的根是中间的点,那么我们要将这些点的根变为两边的点,细节什么的仔细想一想就好。

#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#define lson x<<1
#define rson x<<1|1
using namespace std;
int n,m;
int v[210][210];
struct sag
{
	int f[810],c[410],s[2];
	int find(int x)
	{
		return (f[x]==x)?x:(f[x]=find(f[x]));
	}
	friend sag operator + (const sag &a,const sag &b)
	{
		sag c;
		int i;
		c.s[0]=a.s[0]+b.s[0],c.s[1]=a.s[1]+b.s[1];
		for(i=1;i<=n;i++)
		{
			c.c[i]=a.c[i],c.c[i+n]=b.c[i+n],c.f[i]=a.f[i],c.f[i+n]=b.f[i+n],c.f[i+2*n]=a.f[i+n],c.f[i+3*n]=b.f[i];
			if(c.f[i]>n)	c.f[i]+=n;
			if(c.f[i+n]<=n)	c.f[i+n]+=3*n;
			if(c.f[i+2*n]>n)	c.f[i+2*n]+=n;
			if(c.f[i+3*n]<=n)	c.f[i+3*n]+=3*n;
		}
		for(i=1;i<=n;i++)	if(a.c[i+n]==b.c[i]&&c.find(i+2*n)!=c.find(i+3*n))
			c.s[a.c[i+n]]--,c.f[c.f[i+2*n]]=c.f[i+3*n];
		//for(i=1;i<=(n<<2);i++)	c.find(i),c.find(i+2*n);
		for(i=1;i<=(n<<1);i++)	if(c.find(i)>2*n)	c.f[c.f[i]]=i,c.f[i]=i;
		for(i=1;i<=(n<<1);i++)	c.find(i);
		return c;
	}
}s[810];
inline int rd()
{
	int ret=0,f=1;	char gc=getchar();
	while(gc<'0'||gc>'9')	{if(gc=='-')	f=-f;	gc=getchar();}
	while(gc>='0'&&gc<='9')	ret=ret*10+(gc^'0'),gc=getchar();
	return ret*f;
}
void build(int l,int r,int x)
{
	if(l==r)
	{
		for(int i=1;i<=n;i++)
		{
			s[x].c[i]=s[x].c[i+n]=v[l][i];
			if(i!=1&&v[l][i]==v[l][i-1])	s[x].f[i]=s[x].f[i+n]=s[x].f[i-1];
			else	s[x].f[i]=s[x].f[i+n]=i,s[x].s[v[l][i]]++;
		}
		return ;
	}
	int mid=(l+r)>>1;
	build(l,mid,lson),build(mid+1,r,rson);
	s[x]=s[lson]+s[rson];
}
void updata(int l,int r,int x,int a,int b)
{
	if(l==r)
	{
		s[x].c[b]^=1,s[x].c[b+n]^=1,s[x].s[0]=s[x].s[1]=0;
		for(int i=1;i<=n;i++)
		{
			if(i!=1&&s[x].c[i]==s[x].c[i-1])	s[x].f[i]=s[x].f[i+n]=s[x].f[i-1];
			else	s[x].f[i]=s[x].f[i+n]=i,s[x].s[s[x].c[i]]++;
		}
		return ;
	}
	int mid=(l+r)>>1;
	if(a<=mid)	updata(l,mid,lson,a,b);
	else	updata(mid+1,r,rson,a,b);
	s[x]=s[lson]+s[rson];
}
int main()
{
	n=rd();
	int i,j,a,b;
	for(i=1;i<=n;i++)	for(j=1;j<=n;j++)	v[i][j]=rd();
	build(1,n,1);
	m=rd();
	for(i=1;i<=m;i++)
	{
		a=rd(),b=rd();
		updata(1,n,1,a,b);
		printf("%d %d\n",s[1].s[1],s[1].s[0]);
	}
	return 0;
}//5 0 1 0 0 0 0 1 1 1 0 1 0 0 0 1 0 0 1 0 0 1 0 0 0 0 2 3 2 2 3
posted @ 2017-12-02 16:05  CQzhangyu  阅读(469)  评论(0编辑  收藏  举报