BZOJ 3282 Tree
2017.11.20
2017.11.20
给定N个点以及每个点的权值,要你处理接下来的M个操作.操作有4种.操作从0到3编号.点从1到N编号.
操作如下:
用LCT维护树上信息就可以了。
Splay()首先要从上到下做一通pushdown(),查询父亲的时候记得pushdown(),link()的时候记得pushup().
#include <cstdio>
#include <algorithm>
using namespace std;
#define N 300010
int n,m,md,ix,iy,fa[N],c[2][N],v[N],t[N];
bool rev[N];
inline int RI()
{
int ret=0;
char tmp=getchar();
while(tmp<'0'||tmp>'9') tmp=getchar();
while(tmp>='0'&&tmp<='9') ret=ret*10+tmp-'0',tmp=getchar();
return ret;
}
inline void pushup(int pos)
{
v[pos]=v[c[0][pos]]^v[c[1][pos]]^t[pos];
}
inline void pushdown(int pos)
{
if(rev[pos])
{
swap(c[0][c[0][pos]],c[1][c[0][pos]]);
swap(c[0][c[1][pos]],c[1][c[1][pos]]);
rev[c[0][pos]]^=1,rev[c[1][pos]]^=1;
rev[pos]=false;
}
}
inline bool isroot(int pos)
{
return c[0][fa[pos]]!=pos&&c[1][fa[pos]]!=pos;
}
void init(int pos)
{
if(!isroot(pos)) init(fa[pos]);
pushdown(pos);
}
inline void rotate(int tx)
{
int ty=fa[tx],tz=fa[ty],tl=(c[1][ty]==tx),tr=tl^1;
if(!isroot(ty)) c[c[1][tz]==ty][tz]=tx;
fa[tx]=tz,fa[ty]=tx;
fa[c[tr][tx]]=ty,c[tl][ty]=c[tr][tx],c[tr][tx]=ty;
pushup(ty),pushup(tx);
}
inline void splay(int tx)
{
init(tx);
while(!isroot(tx))
{
int ty=fa[tx],tz=fa[ty];
if(!isroot(ty))
{
if((c[0][ty]==tx)^(c[0][tz]==ty)) rotate(tx);
else rotate(ty);
}
rotate(tx);
}
}
inline void access(int pos)
{
int tmp=0;
while(pos)
{
splay(pos);
c[1][pos]=tmp;
pushup(pos);
tmp=pos,pos=fa[pos];
}
}
inline void cgroot(int pos)
{
access(pos),splay(pos);
swap(c[0][pos],c[1][pos]);
rev[pos]^=1;
}
inline void cut(int tx,int ty)
{
cgroot(tx),access(ty),splay(ty);
if(c[0][ty]==tx) c[0][ty]=fa[tx]=0,pushup(ty);
}
inline int lookfor(int pos)
{
access(pos),splay(pos);
while(c[0][pos]) pushdown(pos),pos=c[0][pos];
return pos;
}
inline void link(int tx,int ty)
{
if(lookfor(tx)!=lookfor(ty))
cgroot(tx),fa[tx]=ty;
}
inline int query(int tx,int ty)
{
cgroot(tx),access(ty),splay(ty);
return v[ty];
}
inline void changev()
{
splay(ix);
v[ix]=v[ix]^t[ix]^iy;
t[ix]=iy;
}
int main()
{
n=RI(),m=RI();
for(int i=1;i<=n;++i) scanf("%d",v+i),t[i]=v[i];
while(m--)
{
md=RI(),ix=RI(),iy=RI();
switch(md)
{
case 0: printf("%d\n",query(ix,iy));break;
case 1: link(ix,iy);break;
case 2: cut(ix,iy);break;
case 3: changev();break;
}
}
return 0;
}