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
1
2
3
1 1 2
0 1 2
0 1 1
Sample Output
3
1
1
HINT
1<=N,M<=300000
竟然找到水题了……
结果洛谷上有这题,竟然贴了个很老旧的……于是大致整改了一下。
#include<bits/stdc++.h>
using namespace std;
int read(){
int x=0,f=1;char ch=getchar();
while (ch<'0' || ch>'9'){if (ch=='-') f=-1;ch=getchar();}
while (ch>='0' && ch<='9'){x=x*10+ch-'0';ch=getchar();}
return x*f;
}
const int
N=300005;
int n,m;
struct LCT{
int val,xsum,pre,son[2];
bool rev;
}tree[N];
bool isroot(int x){
return tree[tree[x].pre].son[0]!=x &&
tree[tree[x].pre].son[1]!=x;
}
void up(int x){
if (x){
tree[x].xsum=tree[x].val;
if (tree[x].son[0]) tree[x].xsum^=tree[tree[x].son[0]].xsum;
if (tree[x].son[1]) tree[x].xsum^=tree[tree[x].son[1]].xsum;
}
}
void down(int x){
if (x && tree[x].rev){
swap(tree[x].son[0],tree[x].son[1]);
tree[tree[x].son[0]].rev^=1;
tree[tree[x].son[1]].rev^=1;
tree[x].rev^=1;
}
}
void Rotate(int x){
int y=tree[x].pre,z=tree[y].pre,l,r;
if (tree[y].son[0]==x) l=0; else l=1;
r=l^1;
if (!isroot(y))
if (tree[z].son[0]==y) tree[z].son[0]=x;
else tree[z].son[1]=x;
tree[x].pre=z,tree[y].pre=x;
tree[y].son[l]=tree[x].son[r];
tree[tree[x].son[r]].pre=y;
tree[x].son[r]=y;
up(y);
}
int stk[N];
void splay(int x){
int top=1;stk[1]=x;
for (int i=x;!isroot(i);i=tree[i].pre)
stk[++top]=tree[i].pre;
while (top) down(stk[top--]);
while (!isroot(x)){
int y=tree[x].pre,z=tree[y].pre;
if (!isroot(y))
if (tree[y].son[0]==x^tree[z].son[0]==y) Rotate(x);
else Rotate(y);
Rotate(x);
}
up(x);
}
void access(int x){
for (int t=0;x;t=x,x=tree[x].pre)
splay(x),tree[x].son[1]=t,up(x);
}
void makeroot(int x){
access(x),splay(x);
tree[x].rev^=1;
}
int findroot(int x){
access(x),splay(x);
while (tree[x].son[0]) x=tree[x].son[0];
return x;
}
void split(int x,int y){
makeroot(x);
access(y),splay(y);
}
void cut(int x,int y){
split(x,y);
tree[y].son[0]=tree[x].pre=0;
}
void link(int x,int y){
makeroot(x);
tree[x].pre=y;
}
int main(){
n=read(),m=read();
for (int i=1;i<=n;i++) tree[i].val=tree[i].xsum=read();
int opt,x,y;
while (m--){
opt=read(),x=read(),y=read();
if (!opt){
split(x,y);
printf("%d\n",tree[y].xsum);
}
if (opt==1 && findroot(x)!=findroot(y)) link(x,y);
if (opt==2 && findroot(x)==findroot(y)) cut(x,y);
if (opt==3){
access(x),splay(x);
tree[x].val=y;
up(x);
}
}
return 0;
}