题目背景
动态树
题目描述
给定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。
输入输出格式
输入格式:
第1行两个整数,分别为N和M,代表点数和操作数。
第2行到第N+1行,每行一个整数,整数在[1,10^9]内,代表每个点的权值。
第N+2行到第N+M+1行,每行三个整数,分别代表操作类型和操作所需的量。
输出格式:
对于每一个0号操作,你须输出X到Y的路径上点权的Xor和。
输入输出样例
输入样例#1:
3 3
1
2
3
1 1 2
0 1 2
0 1 1
输出样例#1:
3
1
说明
1<=N,M<=300000
代码
#include<cstdio>
#include<cstring>
#include<iostream>
#include<cmath>
#include<algorithm>
#define N 300005
int fa[N],rev[N],xr[N],v[N],c[N][2],q[N];
int n,m;
using namespace std;
inline int read()
{
int x=0;char ch=getchar();
while (ch<'0'||ch>'9') ch=getchar();
while (ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
return x;
}
inline bool isroot(int x)
{
return c[fa[x]][0]!=x&&c[fa[x]][1]!=x;
}
inline void pushdown(int x)
{
int l=c[x][0],r=c[x][1];
if (rev[x])
{
rev[x]^=1;rev[l]^=1;rev[r]^=1;
swap(c[x][0],c[x][1]);
}
}
inline void update(int x)
{
xr[x]=v[x]^xr[c[x][0]]^xr[c[x][1]];
}
inline void rotate(int x)
{
int l,r,y=fa[x],z=fa[y];
if (c[y][0]==x) l=0;else l=1;r=l^1;
if (!isroot(y))
{
if (c[z][0]==y) c[z][0]=x;else c[z][1]=x;
}
fa[x]=z;fa[y]=x;
fa[c[x][r]]=y;
c[y][l]=c[x][r];
c[x][r]=y;
update(y);update(x);
}
inline void splay(int x)
{
int top=0;
q[++top]=x;
for (int i=x;!isroot(i);i=fa[i])
q[++top]=fa[i];
while (top) pushdown(q[top--]);
while (!isroot(x))
{
int y=fa[x],z=fa[y];
if (!isroot(y))
{
if (c[z][0]==y^c[y][0]==x) rotate(x);else rotate(y);
}
rotate(x);
}
}
inline void access(int x)
{
int t=0;
while (x)
{
splay(x);
c[x][1]=t;
update(x);
t=x;
x=fa[x];
}
}
inline void makeroot(int x)
{
access(x);
splay(x);
rev[x]^=1;
}
int find(int x)
{
access(x);
splay(x);
while (c[x][0]) x=c[x][0];
return x;
}
inline void link(int x,int y)
{
makeroot(x);
fa[x]=y;
}
inline void cut(int x,int y)
{
makeroot(x);
access(y);
splay(y);
if (c[y][0]!=x) return;
fa[x]=0;
c[y][0]=0;
update(y);
}
int main()
{
n=read();m=read();
for (int i=1;i<=n;i++)
v[i]=read(),xr[i]=v[i];
int opt,x,y;
while (m--)
{
opt=read();x=read();y=read();
if (opt==0)
{
makeroot(x);
access(y);
splay(y);
printf("%d\n",xr[c[y][0]]^v[y]);
}
else if (opt==1)
{
if (find(x)!=find(y)) link(x,y);
}
else if (opt==2)
{
cut(x,y);
}
else
{
access(x);
splay(x);
v[x]=y;
xr[x]=xr[c[x][0]]^v[x];
}
}
return 0;
}
版权声明:本文为w_yqts原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。