uoj#207. 共价大爷游长沙

传送门

lct维护子树信息。

加入一条路径时给两个端点x,y分别异或上rand出来的一个权值,那么若一条边被所有路径经过,即所有路径的两端点都分居这条边的两边,那么这条边一端的子树权值异或和为总的路径的权值异或和。

跟上一道题一样用lct维护子树信息即可。

  1 //Achen
  2 #include<algorithm>
  3 #include<iostream>
  4 #include<cstring>
  5 #include<cstdlib>
  6 #include<cstdio>
  7 #include<vector>
  8 #include<queue>
  9 #include<cmath>
 10 #include<ctime>
 11 #define For(i,a,b) for(int i=(a);i<=(b);i++)
 12 #define Rep(i,a,b) for(int i=(a);i>=(b);i--)
 13 const int N=3e5+7;
 14 typedef long long LL;
 15 typedef double db;
 16 using namespace std;
 17 int n,m,ch[N][2],p[N],sum[N],flip[N],sz[N],S,op[N][3],cq;
 18 
 19 template<typename T> void read(T &x) {
 20     T f=1; x=0; char ch=getchar();
 21     while(ch!='-'&&(ch<'0'||ch>'9')) ch=getchar();
 22     if(ch=='-') f=-1,ch=getchar();
 23     for(;ch>='0'&&ch<='9';ch=getchar()) x=x*10+ch-'0'; x*=f;
 24 }
 25 
 26 #define lc ch[x][0]
 27 #define rc ch[x][1]
 28 int isroot(int x) { return (ch[p[x]][0]!=x&&ch[p[x]][1]!=x); }
 29 
 30 void update(int x) { sum[x]=(sum[lc]^sum[rc]^sz[x]); } //sum:总信息 sz:虚儿子和自己的信息 
 31 
 32 void down(int x) {
 33     if(!flip[x]) return;
 34     swap(lc,rc);
 35     flip[x]^=1;
 36     flip[lc]^=1;
 37     flip[rc]^=1;
 38 } 
 39 
 40 void rotate(int x) {
 41     int y=p[x],z=p[y],l=(x==ch[y][1]),r=l^1;
 42     if(!isroot(y)) ch[z][y==ch[z][1]]=x; p[x]=z;
 43     ch[y][l]=ch[x][r]; p[ch[x][r]]=y;
 44     ch[x][r]=y; p[y]=x;
 45     update(y); update(x);
 46 }
 47 
 48 void splay(int x) {
 49     static int g[N],top=0,tp;
 50     for(tp=x;!isroot(tp);tp=p[tp]) g[++top]=tp;
 51     g[++top]=tp;
 52     while(top) {down(g[top--]);}
 53     for(;!isroot(x);rotate(x)) {
 54         int y=p[x],z=p[y];
 55         if(!isroot(y)) 
 56             ((x==ch[y][1])^(y==ch[z][1]))?rotate(x):rotate(y);
 57     }
 58 }
 59 
 60 void access(int x) {
 61     for(int t=0;x;x=p[t=x]) {
 62         splay(x);
 63         sz[x]^=(sum[rc]^sum[t]); 
 64         rc=t;
 65         update(x);
 66     }
 67 }
 68 
 69 void newroot(int x) {
 70     access(x);
 71     splay(x);
 72     flip[x]^=1;
 73 }
 74 
 75 void cut(int x,int y) {
 76     newroot(x);
 77     access(y);
 78     splay(y);
 79     ch[y][0]=p[x]=0;
 80     update(y);
 81 } 
 82 
 83 void lik(int x,int y) {
 84     newroot(x); 
 85     newroot(y);
 86     splay(x); 
 87     p[x]=y; 
 88     sz[y]^=sum[x]; 
 89     update(y);
 90 }
 91 
 92 void change(int x,int w) {
 93     access(x); 
 94     splay(x);
 95     sz[x]^=w;
 96     update(x);
 97 }
 98 
 99 int main() {
100     int tp;
101     read(tp);
102     srand(998244353);
103     read(n); read(m);
104     for(int i=2;i<=n;i++) {
105         int x,y;
106         read(x); read(y);
107         lik(x,y);
108     }
109     while(m--) { 
110         int o,x,y,w;
111         read(o); 
112         if(o==1) {
113             read(x); read(y); cut(x,y);
114             read(x); read(y); lik(x,y);
115         }
116         else if(o==2) {
117             read(x); read(y); w=rand();
118             change(x,w); change(y,w); S^=w;
119             op[++cq][0]=x; op[cq][1]=y; op[cq][2]=w;
120         }
121         else if(o==3) {
122             read(o);
123             x=op[o][0]; y=op[o][1]; w=op[o][2];
124             S^=w; change(x,w); change(y,w); 
125         }
126         else if(o==4) {
127             read(x); read(y);
128             newroot(x); 
129             access(y);
130             if((sz[y])==S) puts("YES");
131             else puts("NO");
132         }
133     }
134     return 0;
135 }
View Code

 

posted @ 2018-03-11 14:46  啊宸  阅读(195)  评论(0编辑  收藏  举报