• 【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
    ",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
  • 相关阅读:
    Tomcat6 一些调优设置内存和连接数
    【原创】使用c3p0数据库连接池时出现com.mchange.v2.resourcepool.TimeoutException
    JVM内存的设置
    JBOSS以及tomcat最大连接数配置和jvm内存配置
    摘抄python __init__
    Python中__init__方法介绍
    Python 绝对简明手册
    python中eval, exec, execfile,和compile [转载]
    extern、static、auto、register 定义变量的不同用法
    Python 网络编程说明
  • 原文地址:https://www.cnblogs.com/CQzhangyu/p/7954565.html
Copyright © 2020-2023  润新知