zoukankan      html  css  js  c++  java
  • UOJ#207. 共价大爷游长沙 LCT

    原文链接https://www.cnblogs.com/zhouzhendong/p/UOJ207.html

    题解

      第一次听说 LCT 还可以维护子树信息。

      首先对于每一条路径 rand 一个值,分别放在两个端点上,于是询问一条边是否被所有路径的经过就变成了询问某一边所代表的子树是否包含所有路径的端点各一次。于是我求出子树 xor ,并与当前所有路径值的 xor 比较是否相同就可以判断了。

      于是接下来就变成了 LCT 维护子树 xor 。

      考虑在 LCT 的时候,再对于每一个节点维护其虚儿子的信息。由于 LCT 涉及虚儿子的操作十分少,所以只需要在修改边的虚实关系的时候顺便维护一下就好了。

      时间复杂度 $O((n+m)log n)$ 。

    代码

    #include <bits/stdc++.h>
    #define link __zzd001
    using namespace std;
    typedef long long LL;
    int read(){
        int x=0;
        char ch=getchar();
        while (!isdigit(ch))
            ch=getchar();
        while (isdigit(ch))
            x=(x<<1)+(x<<3)+ch-48,ch=getchar();
        return x;
    }
    const int N=100005;
    int n,m,id;
    int fa[N],son[N][2],rev[N],val[N],sum[N];
    void pushup(int x){
    	sum[x]=sum[son[x][0]]^val[x]^sum[son[x][1]];
    }
    int isroot(int x){
    	return son[fa[x]][0]!=x&&son[fa[x]][1]!=x;
    }
    int wson(int x){
    	return son[fa[x]][1]==x;
    }
    void rotate(int x){
    	if (isroot(x))
    		return;
    	int y=fa[x],z=fa[y],L=wson(x),R=L^1;
    	if (!isroot(y))
    		son[z][wson(y)]=x;
    	fa[x]=z,fa[y]=x,fa[son[x][R]]=y;
    	son[y][L]=son[x][R],son[x][R]=y;
    	pushup(y),pushup(x);
    }
    void pushdown(int x){
    	if (rev[x]){
    		swap(son[x][0],son[x][1]);
    		rev[son[x][0]]^=1;
    		rev[son[x][1]]^=1;
    		rev[x]=0;
    	}
    }
    void pushadd(int x){
    	if (!isroot(x))
    		pushadd(fa[x]);
    	pushdown(x);
    }
    void splay(int x){
    	pushadd(x);
    	for (int y=fa[x];!isroot(x);rotate(x),y=fa[x])
    		if (!isroot(y))
    			rotate(wson(x)==wson(y)?y:x);
    }
    void access(int x){
    	for (int t=0;x;t=x,x=fa[x]){
    		splay(x);
    		val[x]^=sum[son[x][1]]^sum[t];
    		fa[t]=x,son[x][1]=t;
    		pushup(x);
    	}
    }
    void rever(int x){
    	access(x),splay(x),rev[x]^=1;
    }
    void link(int x,int y){
    	rever(x),rever(y);
    	fa[x]=y,val[y]^=sum[x];
    	pushup(y);
    }
    void cut(int x,int y){
    	rever(x),access(y),splay(y);
    	son[y][0]=fa[x]=0;
    	pushup(y);
    }
    int randv[N*3],rands=0,cnt=0;
    pair <int,int> path[N*3];
    int randint(){
    	int a=rand()&65535,b=rand()&65535;
    	return (a<<15)^b;
    }
    int main(){
    	srand('C'+'L'+'Y'+'A'+'K'+'I'+'O'+'I');
    	id=read(),n=read(),m=read();
    	for (int i=1;i<n;i++){
    		int x=read(),y=read();
    		link(x,y);
    	}
    	while (m--){
    		int opt=read(),x,y,u,v;
    		if (opt==1){
    			x=read(),y=read(),u=read(),v=read();
    			cut(x,y),link(u,v);
    		}
    		else if (opt==2){
    			x=read(),y=read();
    			int now=randv[++cnt]=randint();
    			path[cnt]=make_pair(x,y);
    			rever(x),val[x]^=now,pushup(x);
    			rever(y),val[y]^=now,pushup(y);
    			rands^=now;
    		}
    		else if (opt==3){
    			u=read();
    			int now=randv[u];
    			x=path[u].first,y=path[u].second;
    			rever(x),val[x]^=now,pushup(x);
    			rever(y),val[y]^=now,pushup(y);
    			rands^=now;
    		}
    		else if (opt==4){
    			x=read(),y=read();
    			rever(x);
    			access(y);
    			splay(y);
    			puts(rands==sum[x]?"YES":"NO");
    		}
    	}
    	return 0;
    }
    

      

  • 相关阅读:
    hibernate的缓存机制
    [poj 3159]Candies[差分约束详解][朴素的考虑法]
    POJ 2773 Happy 2006
    给定一个循环链表,实现一个算法返回这个环的开始结点
    使用jQuery创建模态窗口登陆效果
    实战数据结构(3)_两个单链表间的合并操作
    sql的强大功能(看一条sql解决的复杂业务)
    uva 10905 Children's Game (排序)
    JFinal学习 & Gradle配置续 & Tomcat配置
    Gradle项目学习 & HttpAsyncClient学习 & CountDownLatch学习
  • 原文地址:https://www.cnblogs.com/zhouzhendong/p/UOJ207.html
Copyright © 2011-2022 走看看