BZOJ 3282: Tree (LCT)题解

来源:互联网 发布:vb 打开文件管理器 编辑:程序博客网 时间:2024/06/06 16:39

Time Limit: 30 Sec Memory Limit: 512 MB
Submit: 2119 Solved: 973


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


Sample Output

3

1


HINT

1<=N,M<=300000


Source

动态树


裸LCT,如果不会LCT的朋友可以以这道题为LCT第一题,因为非常的裸,还可以看我的LCT讲解


#include<cstdio>#include<cstring>#include<algorithm>#include<iostream>const int MAXN=300010;using namespace std;struct Tree{    int child[2],sum,val,fa,rev;}tree[MAXN];int n,Q,opt,xx,yy;void pushup(int x){tree[x].sum=tree[tree[x].child[0]].sum^tree[tree[x].child[1]].sum^tree[x].val;}void pushdown(int x){    if(tree[x].rev){        tree[x].rev^=1;        tree[tree[x].child[0]].rev^=1;        tree[tree[x].child[1]].rev^=1;        swap(tree[x].child[0],tree[x].child[1]);    }}bool isroot(int x){    return (tree[tree[x].fa].child[0]!=x)&&(tree[tree[x].fa].child[1]!=x);}void Pushdown(int x){    if(!isroot(x)) Pushdown(tree[x].fa);    pushdown(x);}void rotate(int x){    int y=tree[x].fa,z=tree[y].fa,l,r;    if(tree[y].child[0]==x) l=0;else l=1;r=l^1;    if(!isroot(y)){        if(tree[z].child[0]==y)tree[z].child[0]=x;        else                   tree[z].child[1]=x;    }    tree[x].fa=z;tree[y].fa=x;tree[tree[x].child[r]].fa=y;    tree[y].child[l]=tree[x].child[r];tree[x].child[r]=y;    pushup(y);pushup(x);}void splay(int x){    Pushdown(x);    while(!isroot(x)){        int y=tree[x].fa,z=tree[y].fa;        if(!isroot(y)){            if((tree[y].child[0]==x)^(tree[z].child[0]==y)) rotate(x);            else rotate(y);        }        rotate(x);    }}void access(int x){for(register int i=0;x;i=x,x=tree[x].fa){splay(x);tree[x].child[1]=i;pushup(x);}}void reverse(int x){access(x);splay(x);tree[x].rev^=1;}int findroot(int x){access(x);splay(x);while(tree[x].child[0])x=tree[x].child[0];return x;}void link(int x,int y){reverse(x);tree[x].fa=y;}void cnt(int x,int y){reverse(x);access(y);splay(y);if(tree[y].child[0]==x) tree[y].child[0]=tree[x].fa=0;}int main(){    scanf("%d%d",&n,&Q);    for(register int i=1;i<=n;i++)scanf("%d",&tree[i].val),tree[i].sum=tree[i].val;    while(Q--){        scanf("%d%d%d",&opt,&xx,&yy);        switch(opt){            case 0:reverse(xx);access(yy);splay(yy); printf("%d\n",tree[yy].sum);break;            case 1:if(findroot(xx)!=findroot(yy)) link(xx,yy);break;            case 2:if(findroot(xx)==findroot(yy)) cnt(xx,yy);break;            case 3:access(xx);splay(xx);tree[xx].val=yy;pushup(xx);break;        }    }    return 0;}

这里写图片描述