BZOJ 3282 Tree link cut trees

来源:互联网 发布:php 上传图片卡住 编辑:程序博客网 时间:2024/05/22 12:01

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






传送门
竟然找到水题了……

结果洛谷上有这题,竟然贴了个很老旧的……于是大致整改了一下。



#include<bits/stdc++.h>using namespace std;int read(){    int x=0,f=1;char ch=getchar();    while (ch<'0' || ch>'9'){if (ch=='-') f=-1;ch=getchar();}    while (ch>='0' && ch<='9'){x=x*10+ch-'0';ch=getchar();}    return x*f;}const int     N=300005;int n,m;struct LCT{    int val,xsum,pre,son[2];bool rev;}tree[N];bool isroot(int x){    return tree[tree[x].pre].son[0]!=x &&           tree[tree[x].pre].son[1]!=x;}void up(int x){    if (x){        tree[x].xsum=tree[x].val;        if (tree[x].son[0]) tree[x].xsum^=tree[tree[x].son[0]].xsum;        if (tree[x].son[1]) tree[x].xsum^=tree[tree[x].son[1]].xsum;    }}void down(int x){    if (x && tree[x].rev){        swap(tree[x].son[0],tree[x].son[1]);        tree[tree[x].son[0]].rev^=1;        tree[tree[x].son[1]].rev^=1;        tree[x].rev^=1;    }}void Rotate(int x){      int y=tree[x].pre,z=tree[y].pre,l,r;      if (tree[y].son[0]==x) l=0; else l=1;      r=l^1;      if (!isroot(y))          if (tree[z].son[0]==y) tree[z].son[0]=x;              else tree[z].son[1]=x;      tree[x].pre=z,tree[y].pre=x;      tree[y].son[l]=tree[x].son[r];      tree[tree[x].son[r]].pre=y;      tree[x].son[r]=y;      up(y);  }  int stk[N];  void splay(int x){      int top=1;stk[1]=x;      for (int i=x;!isroot(i);i=tree[i].pre)          stk[++top]=tree[i].pre;      while (top) down(stk[top--]);      while (!isroot(x)){          int y=tree[x].pre,z=tree[y].pre;          if (!isroot(y))              if (tree[y].son[0]==x^tree[z].son[0]==y) Rotate(x);                  else Rotate(y);          Rotate(x);      }      up(x);  }  void access(int x){for (int t=0;x;t=x,x=tree[x].pre)    splay(x),tree[x].son[1]=t,up(x);}void makeroot(int x){    access(x),splay(x);    tree[x].rev^=1;}int findroot(int x){    access(x),splay(x);    while (tree[x].son[0]) x=tree[x].son[0];    return x;}void split(int x,int y){    makeroot(x);    access(y),splay(y); }void cut(int x,int y){    split(x,y);    tree[y].son[0]=tree[x].pre=0;}void link(int x,int y){    makeroot(x);    tree[x].pre=y;}int main(){    n=read(),m=read();    for (int i=1;i<=n;i++) tree[i].val=tree[i].xsum=read();    int opt,x,y;    while (m--){        opt=read(),x=read(),y=read();        if (!opt){            split(x,y);            printf("%d\n",tree[y].xsum);        }        if (opt==1 && findroot(x)!=findroot(y)) link(x,y);        if (opt==2 && findroot(x)==findroot(y)) cut(x,y);        if (opt==3){            access(x),splay(x);            tree[x].val=y;            up(x);        }    }    return 0;}

原创粉丝点击