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。
Input
第1行两个整数,分别为N和M,代表点数和操作数。
第2行到第N+1行,每行一个整数,整数在[1,10^9]内,代表每个点的权值。
第N+2行到第N+M+1行,每行三个整数,分别代表操作类型和操作所需的量。
Output
对于每一个0号操作,你须输出X到Y的路径上点权的Xor和。
Sample Input
3 3
1
2
3
1 1 2
0 1 2
0 1 1
Sample Output
3
1
Hint
1<=N,M<=300000
简单的维护点权信息,裸题。(LCT取链操作比较重要)
#include<bits/stdc++.h>
using namespace std;
#define Inc(i,L,r) for(register int i=(L);i<=(r);++i)
const int N = 3e5+10;
int n,m;
struct Splay{
bool rev[N];
int p[N],ch[N][2];
int vl[N],sum[N];
#define Ls(v) ch[v][0]
#define rs(v) ch[v][1]
inline bool is_root(int x){
return (Ls(p[x])^x)&&(rs(p[x])^x);
}
inline void maintain(int x){
sum[x]=sum[Ls(x)]^vl[x]^sum[rs(x)];
}
inline void pushdown(int x){
if(rev[x]){
rev[Ls(x)]^=1,rev[rs(x)]^=1;
swap(Ls(x),rs(x));
rev[x]=0;
}
}
inline void rot(int x){
int f=p[x],gf=p[f],type=rs(f)==x,son=ch[x][!type];
if(!is_root(f))ch[gf][rs(gf)==f]=x;p[x]=gf;
ch[p[son]=f][type]=son,maintain(f);
ch[p[f]=x][!type]=f,maintain(x);
}
int top,stk[N];
inline void splay(int x){
stk[++top]=x;
if(!is_root(x))for(int i=x;!is_root(i);i=p[i])stk[++top]=p[i];
while(top)pushdown(stk[top--]);
while(!is_root(x)){
if(is_root(p[x]))return rot(x),void();
if((rs(p[p[x]])==p[x])==(rs(p[x])==x))rot(p[x]);
rot(x);
}
}
inline int findrt(int x){
while(Ls(x))x=Ls(x);
return x;
}
};
struct LCT{
Splay sp;
inline void access(int x){
for(int lastx=0;x;lastx=x,x=sp.p[x])
sp.splay(x),sp.rs(x)=lastx,sp.maintain(x);
}
inline void make_root(int x){
access(x),sp.splay(x),sp.rev[x]^=1;
}
inline void link(int x,int y){
make_root(x),sp.p[x]=y;
}
inline void cut(int x,int y){
make_root(x),access(y),sp.splay(y);
sp.p[x]=sp.Ls(y)=0;
}
inline void split(int x,int y){
make_root(x),access(y),sp.splay(y);
}
inline bool connect(int x,int y){
int rtx,rty;
access(x),sp.splay(x),rtx=sp.findrt(x);
access(y),sp.splay(y),rty=sp.findrt(y);
return rtx==rty;
}
}lct;
inline void init(){
scanf("%d%d",&n,&m);
Inc(i,1,n)scanf("%d",&lct.sp.vl[i]);
}
inline void solv(){
while(m--){
int op,x,y;scanf("%d%d%d",&op,&x,&y);
switch(op){
case 0:lct.split(x,y);cout<<lct.sp.sum[y]<<"\n";break;
case 1:if(!lct.connect(x,y))lct.link(x,y);break;
case 2:if(lct.connect(x,y))lct.cut(x,y);break;
case 3:lct.sp.vl[x]=y,lct.sp.splay(x),lct.sp.maintain(x);break;
}
}
}
int main(){
init();
solv();
return 0;
}