【UOJ#207】共价大爷游长沙

  • 本文为博主原创,未经许可不得转载

这题好神啊,谁能想到随机化的做法呢?

给每条路径随机一个权值,并给两个端点异或上这个权值

那么一条边在所有路径上的条件是边的两个端点的子树异或和都等于所有路径的异或和

用LCT维护子树异或和就行了

最后提醒一下:异或的优先级低于等于,博主因为这个被卡的好惨

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
#include<bits/stdc++.h>
#define FILE "read"
#define MAXN 300100
using namespace std;
int Case,n,m,cnt,now,value[MAXN],sum[MAXN],Vsum[MAXN],S[MAXN][3];
char buf[1<<15],*fs,*ft;
inline char getc(){return (fs==ft&&(ft=(fs=buf)+fread(buf,1,1<<15,stdin),fs==ft))?0:*fs++;}
inline int read(){
int x=0,f=1; char ch=getc();
while(ch>'9'||ch<'0') {if(ch=='-') f=-1; ch=getc();}
while(ch>='0'&&ch<='9') {x=x*10+ch-'0'; ch=getc();}
return x*f;
}
class Link_Cut_Tree{
private:
int f[MAXN],rev[MAXN],st[MAXN],son[MAXN][2];
inline bool get(int x){return son[f[x]][1]==x;}
inline bool isroot(int x){return son[f[x]][0]!=x&&son[f[x]][1]!=x;}
inline void rotate(int x){
int y=f[x],z=f[y],which=get(x);
if(!isroot(y)) son[z][son[z][1]==y]=x;
son[y][which]=son[x][which^1]; f[son[y][which]]=y;
son[x][which^1]=y; f[y]=x; f[x]=z;
updata(y); updata(x);
}
inline 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;
}
}
public:
inline void updata(int x){
sum[x]=Vsum[x]^value[x];
if(son[x][0]) sum[x]^=sum[son[x][0]];
if(son[x][1]) sum[x]^=sum[son[x][1]];
}
inline void splay(int x){
int top(0); st[++top]=x;
for(int i=x;!isroot(i);i=f[i]) st[++top]=f[i];
for(int i=top;i;--i) pushdown(st[i]);
for(int y=f[x];!isroot(x);rotate(x),y=f[x])
if(!isroot(y)) rotate(get(x)==get(y)?y:x);
}
inline void access(int x){
int last=0;
while(x){
splay(x);
if(son[x][1]) Vsum[x]^=sum[son[x][1]];
if(last) Vsum[x]^=sum[last];
son[x][1]=last; updata(x);
last=x; x=f[x];
}
}
inline void reverse(int x){
access(x); splay(x); rev[x]^=1;
}
inline void linkk(int x,int y){
//access(x); splay(x);
reverse(x); reverse(y);
f[y]=x; Vsum[x]^=sum[y];
updata(x);
}
inline void Cut(int x,int y){
reverse(x); access(y); splay(y);
f[x]=son[y][0]=0; updata(y); updata(x);
}
}T;
int main(){
freopen(FILE".in","r",stdin);
freopen(FILE".out","w",stdout);
srand(time(0));
Case=read(); n=read(); m=read();
for(int i=1;i<n;++i){
int x=read(),y=read();
T.linkk(x,y);
}
for(int i=1;i<=m;++i){
int opt=read();
if(opt==1){
int x=read(),y=read(); T.Cut(x,y);
x=read(),y=read(); T.linkk(x,y);
}
else if(opt==2){
S[++cnt][0]=read(); S[cnt][1]=read(); S[cnt][2]=rand()*rand();
T.reverse(S[cnt][0]); value[S[cnt][0]]^=S[cnt][2]; T.updata(S[cnt][0]);
T.reverse(S[cnt][1]); value[S[cnt][1]]^=S[cnt][2]; T.updata(S[cnt][1]);
now^=S[cnt][2];
}
else if(opt==3){
int x=read(); now^=S[x][2];
T.reverse(S[x][0]); value[S[x][0]]^=S[x][2]; T.updata(S[x][0]);
T.reverse(S[x][1]); value[S[x][1]]^=S[x][2]; T.updata(S[x][1]);
}
else if(opt==4){
int x=read(),y=read();
T.reverse(x); T.access(y); T.splay(x);
if((sum[x]^Vsum[y]^value[y])==now&&(Vsum[y]^value[y])==now) puts("YES");
else puts("NO");
}
}
return 0;
}
文章目录
,