题目描述
给定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。
#include<bits/stdc++.h>
#define N 100005
#define ls t[x].ch[0]
#define rs t[x].ch[1]
using namespace std;
struct Node{
int ch[2],fa,val,tag;
}t[N];
int n,m,v[N],ans,sta[N];
int read(){
int cnt=0,f=1;char ch=0;
while(!isdigit(ch)){if(ch=='-')f=-1;ch=getchar();}
while(isdigit(ch))cnt=cnt*10+(ch-'0'),ch=getchar();
return cnt*f;
}
bool isRoot(int x){
int fa=t[x].fa; if(fa==0) return true;
return t[fa].ch[0]!=x && t[fa].ch[1]!=x;
}
void Pushup(int x){
t[x].val=t[ls].val^v[x]^t[rs].val;
}
void Pushrev(int x){
if(!x) return; swap(ls,rs); t[x].tag ^= 1;
}
void Pushdown(int x){
if(t[x].tag){
Pushrev(ls); Pushrev(rs);
t[x].tag=0;
}
}
void Pushpath(int x){
if(!isRoot(x)) Pushpath(t[x].fa);
Pushdown(x);
}
void rotate(int x){
int y=t[x].fa,z=t[y].fa;
int k=t[y].ch[1]==x;
if(!isRoot(y)) t[z].ch[t[z].ch[1]==y]=x;
t[x].fa=z;
t[y].ch[k]=t[x].ch[k^1];
t[t[x].ch[k^1]].fa=y;
t[x].ch[k^1]=y,t[y].fa=x;
Pushup(y),Pushup(x);
}
void Splay(int x){
Pushpath(x);
while(!isRoot(x)){
int y=t[x].fa,z=t[y].fa;
if(!isRoot(y))
(t[y].ch[0]==x)^(t[z].ch[0]==y)?rotate(x):rotate(y);
rotate(x);
}Pushup(x);
}
void Access(int x){
for(int y=0;x;y=x,x=t[x].fa)
Splay(x),rs=y,Pushup(x);
}
int Findroot(int x){
Access(x),Splay(x);
while(ls) Pushdown(x),x=ls;
return x;
}
void Makeroot(int x){
Access(x),Splay(x),Pushrev(x);
}
void Split(int x,int y){
Makeroot(x),Access(y),Splay(y);
}
void Link(int x,int y){
Makeroot(x);
if(Findroot(y)!=x) t[x].fa=y;
}
bool check(int x,int y){
return Findroot(y)==x && t[x].fa==y && t[y].ch[0]==x && t[y].ch[1]==0;
}
void Cut(int x,int y){
Makeroot(x);
if(check(x,y)){
t[y].ch[0]=0,t[x].fa=0;
Pushup(y);
}
}
int main(){
n=read(),m=read();
for(int i=1;i<=n;i++) v[i]=read();
while(m--){
int op=read(),x=read(),y=read();
if(op==0) Split(x,y),printf("%d\n",t[y].val);
if(op==1) Link(x,y);
if(op==2) Cut(x,y);
if(op==3) Splay(x),v[x]=y;
} return 0;
}