BZOJ_3282_Tree_LCT

BZOJ_3282_Tree_LCT

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行,每行三个整数,分别代表操作类型和操作所需的量。
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

 LCT维护一下点权的xor和,单点修改直接暴力。
修改的时候应该是不用access,但我加上access操作会快一些
 
代码:
#include <stdio.h>
#include <string.h>
#include <algorithm>
using namespace std;
#define N 300050
#define ls ch[p][0]
#define rs ch[p][1]
#define get(x) (ch[f[x]][1]==x)
int ch[N][2],f[N],sum[N],n,m,val[N],rev[N];
inline bool isrt(int p) {
return ch[f[p]][1]!=p&&ch[f[p]][0]!=p;
}
inline void pushdown(int p) {
if(rev[p]) {
swap(ch[ls][0],ch[ls][1]);
swap(ch[rs][0],ch[rs][1]);
rev[ls]^=1; rev[rs]^=1;
rev[p]=0;
}
}
inline void pushup(int p) {
sum[p]=sum[ls]^sum[rs]^val[p];
}
inline void update(int p) {
if(!isrt(p)) update(f[p]);
pushdown(p);
}
void rotate(int x) {
int y=f[x],z=f[y],k=get(x);
if(!isrt(y)) ch[z][ch[z][1]==y]=x;
ch[y][k]=ch[x][!k]; f[ch[y][k]]=y;
ch[x][!k]=y; f[y]=x; f[x]=z;
pushup(y); pushup(x);
}
void splay(int x) {
update(x);
for(int fa;fa=f[x],!isrt(x);rotate(x))
if(!isrt(fa))
rotate(get(fa)==get(x)?fa:x);
}
void access(int p) {
int t=0;
while(p) splay(p),rs=t,pushup(p),t=p,p=f[p];
}
void makeroot(int p) {
access(p); splay(p);
swap(ls,rs); rev[p]^=1;
}
void link(int x,int p) {
makeroot(x); f[x]=p;
}
void cut(int x,int p) {
makeroot(x); access(p); splay(p); ls=f[x]=0;
}
int find(int p) {
access(p); splay(p);
while(ls) pushdown(p),p=ls;
return p;
}
void fix(int x,int v) {
/*access(x);*/ splay(x); sum[x]^=val[x]; val[x]=v; sum[x]^=val[x];
}
int main() {
scanf("%d%d",&n,&m);
int i,x,y,opt;
for(i=1;i<=n;i++) scanf("%d",&val[i]);
for(i=1;i<=m;i++) {
scanf("%d%d%d",&opt,&x,&y);
if(opt==0) {
makeroot(x); access(y); splay(y);
printf("%d\n",sum[y]);
}else if(opt==1) {
int t1=find(x),t2=find(y);
if(t1!=t2) link(x,y);
}else if(opt==2) {
int t1=find(x),t2=find(y);
if(t1==t2) cut(x,y);
}else {
fix(x,y);
}
}
}
上一篇:opencv 中affine函数实现旋转和平移


下一篇:ORACLE表数据误删除的恢复方法(提交事务也可以)