您的位置:首页 > 其它

【BZOJ3282】Tree

2016-01-27 20:53 281 查看
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

动态树

今天写了一天水题..

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
#define MAXN 300010
#define GET (ch>='0'&&ch<='9')
using namespace std;
int n,q;
int sta[MAXN],top;
struct splay
{
int ch[2],fa,sum,val;
bool rev;
}tree[MAXN];
inline void in(int &x)
{
char ch=getchar();x=0;
while (!GET)    ch=getchar();
while (GET) x=x*10+ch-'0',ch=getchar();
}
inline bool is_root(int x)
{
return tree[tree[x].fa].ch[0]!=x&&tree[tree[x].fa].ch[1]!=x;
}
inline void push_up(int x)
{
tree[x].sum=tree[tree[x].ch[0]].sum^tree[tree[x].ch[1]].sum^tree[x].val;
}
inline void push_down(int x)
{
if (tree[x].rev)
{
tree[tree[x].ch[0]].rev^=1;tree[tree[x].ch[1]].rev^=1;
swap(tree[x].ch[0],tree[x].ch[1]);tree[x].rev^=1;
}
}
inline void rot(int x)
{
int y=tree[x].fa,z=tree[y].fa,l,r;
l=(tree[y].ch[1]==x);r=l^1;
if (!is_root(y))    tree[z].ch[tree[z].ch[1]==y]=x;
tree[x].fa=z;tree[tree[x].ch[r]].fa=y;tree[y].fa=x;
tree[y].ch[l]=tree[x].ch[r];tree[x].ch[r]=y;
push_up(y);push_up(x);
}
inline void Splay(int x)
{
sta[++top]=x;
for (int i=x;!is_root(i);i=tree[i].fa)  sta[++top]=tree[i].fa;
while (top) push_down(sta[top--]);
while (!is_root(x))
{
int y=tree[x].fa,z=tree[y].fa;
if (!is_root(y))
{
if ((tree[y].ch[0]==x)^(tree[z].ch[0]==y))  rot(x);
else    rot(y);
}
rot(x);
}
}
inline void access(int x)
{
for (int i=0;x;i=x,x=tree[x].fa)    Splay(x),tree[x].ch[1]=i,push_up(x);
}
inline void make_root(int x)
{
access(x);Splay(x);tree[x].rev^=1;
}
inline int find(int x)
{
for (access(x),Splay(x);tree[x].ch[0];x=tree[x].ch[0]);
return x;
}
inline void link(int x,int y)
{
if (find(x)==find(y))   return;
make_root(x);tree[x].fa=y;
}
inline void cut(int x,int y)
{
if (find(x)!=find(y))   return;
make_root(x);access(y);Splay(y);tree[y].ch[0]=tree[x].fa=0;push_up(y);
}
inline void split(int x,int y)
{
make_root(x);access(y);Splay(y);
}
int main()
{
in(n);in(q);int opt,u,v;
for (int i=1;i<=n;i++)  in(tree[i].val),tree[i].sum=tree[i].val;
while (q--)
{
in(opt);in(u);in(v);
if  (opt==0)    split(u,v),printf("%d\n",tree[v].sum);
if  (opt==1)    link(u,v);
if  (opt==2)    cut(u,v);
if  (opt==3)    access(u),Splay(u),tree[u].val=v,push_up(u);
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  LCT