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 }