您的位置:首页 > 其它

[UOJ207]共价大爷游长沙

2018-01-24 21:25 369 查看
如果每次加入点对$(x,y)$,就给它一个随机的权值$v$,把两个点的点权都异或$v$,查询$(x,y)$的时候,只要把$x$硬点为根,以$y$为根的子树的异或和等于当前所有的异或和,那么很大概率就是正确的(每对点刚好有一个在$y$的子树中)

所以直接用lct维护即可,因为维护了虚边信息,所以link时两边都要makeroot(不然没法更新splay里的祖先的信息),cut时不改虚边信息

splay之前一定要记得一路pushdown啊啊啊啊啊啊!

虽然yww做了很不对的事但是还是要orzyww

#include<stdio.h>
#include<stdlib.h>
#include<time.h>
int ch[100010][2],fa[100010],r[100010],v[100010],s[100010],vs[100010],q1[300010],q2[300010],d[300010];
#define ls ch[x][0]
#define rs ch[x][1]
void swap(int&a,int&b){a^=b^=a^=b;}
void rev(int x){
swap(ls,rs);
r[x]^=1;
}
bool isrt(int x){return ch[fa[x]][0]!=x&&ch[fa[x]][1]!=x;}
void pushdown(int x){
if(r[x]){
if(ls)rev(ls);
if(rs)rev(rs);
r[x]=0;
}
}
void pushup(int x){s[x]=v[x]^s[ls]^s[rs]^vs[x];}
void rot(int x){
int y,z,f,B;
y=fa[x];
z=fa[y];
f=(ch[y][0]==x);
B=ch[x][f];
fa[x]=z;
fa[y]=x;
if(B)fa[B]=y;
ch[x][f]=y;
ch[y][f^1]=B;
if(ch[z][0]==y)ch[z][0]=x;
if(ch[z][1]==y)ch[z][1]=x;
pushup(y);
pushup(x);
}
void gao(int x){
if(!isrt(x))gao(fa[x]);
pushdown(x);
}
void splay(int x){
int y,z;
gao(x);
while(!isrt(x)){
y=fa[x];
z=fa[y];
if(!isrt(y))rot((ch[z][0]==y&&ch[y][0]==x)||(ch[z][1]==y&&ch[y][1]==x)?y:x);
rot(x);
}
}
void access(int x){
int y=0;
while(x){
splay(x);
vs[x]^=s[rs];
rs=y;
vs[x]^=s[y];
pushup(x);
y=x;
x=fa[x];
}
}
void makert(int x){
access(x);
splay(x);
rev(x);
}
void link(int x,int y){
makert(x);
makert(y);
fa[x]=y;
vs[y]^=s[x];
pushup(y);
}
void cut(int x,int y){
makert(y);
access(x);
splay(x);
fa[y]=ls=0;
pushup(x);
}
void modify(int x,int d){
access(x);
splay(x);
v[x]^=d;
pushup(x);
}
int query(int x,int y){
makert(x);
access(y);
return vs[y]^v[y];
}
int main(){
srand(time(0));
int n,m,i,x,y,sum;
scanf("%d%d%d",&i,&n,&m);
for(i=1;i<n;i++){
scanf("%d%d",&x,&y);
link(x,y);
}
n=sum=0;
while(m--){
scanf("%d",&i);
if(i==1){
scanf("%d%d",&x,&y);
cut(x,y);
scanf("%d%d",&x,&y);
link(x,y);
}
if(i==2){
n++;
scanf("%d%d",q1+n,q2+n);
d
=x=rand()*rand();
sum^=x;
modify(q1
,x);
modify(q2
,x);

}
if(i==3){
scanf("%d",&x);
modify(q1[x],d[x]);
modify(q2[x],d[x]);
sum^=d[x];
}
if(i==4){
scanf("%d%d",&x,&y);
puts(query(x,y)==sum?"YES":"NO");
}
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: