problem
题目背景
动态树
题目描述
给定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 \leq N, M \leq 3 \cdot {10}^5 1≤N,M≤3⋅10
5
analysis
还是LCT板子题
差不多是板子在手天下我有注意两点就好
link,cut l i n k , c u t 的两个点不一定联通,用 judge j u d g e 特判一下
还有就是异或和的话 a[i].sum=(a[i].val)xor(a[t[i][0]].sum)xor(a[t[i][1]].sum) a [ i ] . s u m = ( a [ i ] . v a l ) x o r ( a [ t [ i ] [ 0 ] ] . s u m ) x o r ( a [ t [ i ] [ 1 ] ] . s u m )
如此简单
code
#include<bits/stdc++.h>
#define MAXN 300001
using namespace std;
int t[MAXN][2];
int b[MAXN],fa[MAXN],pf[MAXN],st[MAXN];
char s[10];
int n,m;
struct node
{
int val,sum,mx,size;
bool rev;
}a[MAXN];
int read()
{
int x=0,f=1;
char ch=getchar();
while (ch<'0' || '9'<ch)
{
if (ch=='-')f=-1;
ch=getchar();
}
while ('0'<=ch && ch<='9')
{
x=x*10+ch-'0';
ch=getchar();
}
return x*f;
}
void reverse(int x)
{
if(x)
{
a[x].rev^=1;
swap(t[x][0],t[x][1]);
}
}
void down(int x)
{
if (a[x].rev)
{
reverse(t[x][0]),reverse(t[x][1]);
a[x].rev=0;
}
}
void update(int x)
{
if (x)
{
a[x].size=a[t[x][0]].size+a[t[x][1]].size+1;
a[x].sum=a[x].val^a[t[x][0]].sum^a[t[x][1]].sum;
}
}
void downdata(int x)
{
st[0]=0;
while (x)st[++st[0]]=x,x=fa[x];
while (st[0])down(st[st[0]--]);
}
int lr(int x)
{
return t[fa[x]][1]==x;
}
void rotate(int x)
{
int y=fa[x],k=lr(x);
t[y][k]=t[x][!k];
if (t[x][!k])fa[t[x][!k]]=y;
fa[x]=fa[y];
if (fa[y])t[fa[y]][lr(y)]=x;
t[x][!k]=y;
fa[y]=x,pf[x]=pf[y];
update(y),update(x);
}
void splay(int x, int y)
{
downdata(x);
while (fa[x]!=y)
{
if (fa[fa[x]]!=y)
{
if (lr(x)==lr(fa[x]))rotate(fa[x]);
else rotate(x);
}
rotate(x);
}
}
void access(int x)
{
for (int y=0;x;update(x),y=x,x=pf[x])
{
splay(x,0);
fa[t[x][1]]=0;
pf[t[x][1]]=x;
t[x][1]=y;
fa[y]=x;
pf[y]=0;
}
}
void makeroot(int x)
{
access(x);
splay(x,0);
reverse(x);
}
int getroot(int x)
{
while (fa[x])x=fa[x];
return x;
}
bool judge(int x,int y)
{
makeroot(x);
access(y);
splay(x,0);
return getroot(y)==x;
}
void link(int x,int y)
{
if (!judge(x,y))
{
makeroot(x);
pf[x]=y;
}
}
void cut(int x,int y)
{
if (judge(x,y))
{
makeroot(x);
access(y);
splay(x,0);
t[x][1]=fa[y]=pf[y]=0;
update(x);
}
}
int main()
{
//freopen("readin.txt","r",stdin);
n=read(),m=read();
a[0].val=a[0].sum=0;
for (int i=1;i<=n;i++)
{
splay(i,0);
a[i].val=read();
update(i);
}
while (m--)
{
int z=read(),x=read(),y=read();
if (z==0)
{
makeroot(y);
access(x);
splay(x,0);
printf("%d\n",a[x].sum);
}
else if (z==1)link(x,y);
else if (z==2)cut(x,y);
else
{
splay(x,0);
a[x].val=y;
update(x);
}
}
}