给定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行,每行三个整数,分别代表操作类型和操作所需的量。 1<=N,M<=300000 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
题意:给定N个节点的初始值,现在有M个操作,每次输入opt、x、y,opt情况如下。
0:输出x到y的路径异或和保证x到y是联通的。
1:连接x和y,已经连通则忽略。
2:删除边x和y,如果不连通则忽略。(题目的连通应该还保证了是直接相邻,不然需要记录直接相邻的关系)。
3:把节点x的值改为y。
思路:和上一题差不多,仅仅是多了个删边操作。
#include<cstdio> #include<cstdlib> #include<iostream> #include<algorithm> using namespace std; const int maxn=500010; int val[maxn]; void read(int &x){ char c=getchar(); x=0; for(;c>'9'||c<'0';c=getchar()); for(;c<='9'&&c>='0';c=getchar()) x=(x<<3)+(x<<1)+c-'0'; } struct LCT { int sum[maxn],rev[maxn],ch[maxn][2],fa[maxn],stc[maxn],top; int isroot(int x){ return ch[fa[x]][0]!=x&&ch[fa[x]][1]!=x; } int get(int x){ return ch[fa[x]][1]==x; } void pushdown(int x) { if(!rev[x]||!x) return ; swap(ch[x][0],ch[x][1]); if(ch[x][0]) rev[ch[x][0]]^=1; if(ch[x][1]) rev[ch[x][1]]^=1; rev[x]=0; } void pushup(int x) { sum[x]=val[x]; if(ch[x][0]) sum[x]^=sum[ch[x][0]]; if(ch[x][1]) sum[x]^=sum[ch[x][1]]; } void rotate(int x) { int old=fa[x],fold=fa[old],opt=get(x); if(!isroot(old)) ch[fold][get(old)]=x; fa[x]=fold; ch[old][opt]=ch[x][opt^1]; fa[ch[old][opt]]=old; ch[x][opt^1]=old; fa[old]=x; pushup(old); pushup(x); } void splay(int x) { int top=0; stc[++top]=x; for(int i=x;!isroot(i);i=fa[i]) stc[++top]=fa[i]; for(int i=top;i;i--) pushdown(stc[i]); for(int f;!isroot(x);rotate(x)){ if(!isroot(f=fa[x])) rotate(get(x)==get(f)?f:x); } } void access(int x) { int rson=0; for(;x;rson=x,x=fa[x]){ splay(x); ch[x][1]=rson; pushup(x); } } int find(int x){ access(x); splay(x); while(ch[x][0]) x=ch[x][0]; return x;} void change(int a,int x){ val[a]=x; access(a); splay(a); } int query(int x,int y) { make_root(y); access(x); splay(x); return sum[x]; } void make_root(int x) { access(x); splay(x); rev[x]^=1; } void link(int x,int y) { make_root(x); fa[x]=y; splay(x); } void cut(int x,int y) { make_root(x); access(y); splay(y); fa[x]=ch[y][0]=0; } }S; int main() { int N,M,a,b,opt; scanf("%d%d",&N,&M); for(int i=1;i<=N;i++) read(val[i]); while(M--){ read(opt); read(a); read(b); if(opt==0) printf("%d ",S.query(a,b)); if(opt==1) if(S.find(a)!=S.find(b)) S.link(a,b); if(opt==2) if(S.find(a)==S.find(b)) S.cut(a,b); if(opt==3) S.change(a,b); } return 0; }