Description
给定N个点以及每个点的权值,要你处理接下来的M个操作。
操作有4种。操作从0到3编号。点从1到N编号。
0:后接两个整数(x,y),代表询问从x到y的路径上的点的权值的xor和。
保证x到y是联通的。
1:后接两个整数(x,y),代表连接x到y,若x到Y已经联通则无需连接。
2:后接两个整数(x,y),代表删除边(x,y),不保证边(x,y)存在。
3:后接两个整数(x,y),代表将点X上的权值变成Y。
Solution
LCT板子题,写这个就是为了练手。。。没啥好说的
一个比较坑的地方就是题目“不保证(x,y)存在”,也就是说可能存在x、y连通但是x、y不相邻这样的cut(x,y),这个判一下就好了
Code
#include <stdio.h>
#include <string.h>
#include <algorithm>
#define rep(i,st,ed) for (int i=st;i<=ed;++i)
const int N=300005;
struct treeNode {
int son[2],fa,sum,val;
bool is_root,rev;
} t[N];
int read() {
int x=0,v=1; char ch=getchar();
for (;ch<'0'||ch>'9';v=(ch=='-')?(-1):(v),ch=getchar());
for (;ch<='9'&&ch>='0';x=x*10+ch-'0',ch=getchar());
return x*v;
}
void push_up(int x) {
t[x].sum=t[x].val;
if (t[x].son[0]) t[x].sum^=t[t[x].son[0]].sum;
if (t[x].son[1]) t[x].sum^=t[t[x].son[1]].sum;
}
void push_down(int x) {
if (!x||!t[x].rev) return ;
std:: swap(t[x].son[0],t[x].son[1]);
if (t[x].son[0]) t[t[x].son[0]].rev^=1;
if (t[x].son[1]) t[t[x].son[1]].rev^=1;
t[x].rev=0;
}
void remove(int x) {
if (!t[x].is_root) remove(t[x].fa);
push_down(x);
}
void rotate(int x) {
if (t[x].is_root) return ;
int y=t[x].fa,z=t[y].fa;
int k=t[y].son[1]==x;
t[y].son[k]=t[x].son[!k];
if (t[x].son[!k]) t[t[x].son[!k]].fa=y;
t[y].fa=x; t[x].son[!k]=y;
t[x].fa=z;
if (t[y].is_root) {
t[x].is_root=1;
t[y].is_root=0;
} else t[z].son[t[z].son[1]==y]=x;
push_up(y); push_up(x);
}
void splay(int x) {
remove(x);
for (;!t[x].is_root;) {
int y=t[x].fa,z=t[y].fa;
if (!t[y].is_root) {
if ((t[z].son[1]==y)^(t[y].son[1]==x)) rotate(x);
else rotate(y);
}
rotate(x);
}
}
void access(int x) {
int y=0;
while (x) {
splay(x);
t[t[x].son[1]].is_root=1;
t[t[x].son[1]=y].is_root=0;
push_up(x);
y=x; x=t[x].fa;
}
}
void mroot(int x) {
access(x); splay(x); t[x].rev^=1;
}
void link(int x,int y) {
mroot(x); t[x].fa=y;
}
void cut(int x,int y) {
mroot(x); access(y); splay(y);
if (t[y].son[0]==x&&t[x].son[1]==0) {
t[y].son[0]=t[x].fa=0;
t[x].is_root=1; push_up(y);
}
}
int find(int x) {
access(x); splay(x);
for (;t[x].son[0];) x=t[x].son[0];
return x;
}
int main(void) {
freopen("data.in","r",stdin);
freopen("myp.out","w",stdout);
int n=read(),m=read();
rep(i,1,n) t[i].val=t[i].sum=read(),t[i].is_root=1;
for (int opt,x,y;m--;) {
opt=read(),x=read(),y=read();
if (opt==0) {
mroot(x); access(y); splay(y);
printf("%d\n", t[y].sum);
} else if (opt==1) {
if (find(x)!=find(y)) link(x,y);
} else if (opt==2) {
if (find(x)==find(y)) cut(x,y);
} else {
access(x); splay(x); t[x].val=y; push_up(x);
}
}
return 0;
}