版权声明:转载请声明出处,谢谢配合。 https://blog.csdn.net/zxyoi_dreamer/article/details/82960094
参考题目:洛谷P3690
解析:
联赛完后统一更模板题解析。
代码:
#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define re register
#define gc getchar
#define pc putchar
#define cs const
inline
int getint(){
re int num;
re char c;
while(!isdigit(c=gc()));num=c^48;
while(isdigit(c=gc()))num=(num<<1)+(num<<3)+(c^48);
return num;
}
inline void outint(int a){
static char ch[13];
if(a==0)pc('0');
while(a)ch[++ch[0]]=a-a/10*10,a/=10;
while(ch[0])pc(ch[ch[0]--]^48);
}
typedef struct splay_node *point;
struct splay_node{
point son[2],fa;
bool tag;
int val,xr;
point &lc(){return son[0];}
point &rc(){return son[1];}
void pushdown(){
if(tag){
swap(lc(),rc());
if(lc())lc()->tag^=1;
if(rc())rc()->tag^=1;
tag=0;
}
}
void init(int _val=0){
son[0]=son[1]=fa=NULL;
tag=0;xr=val=_val;
}
void pushup(){
xr=(lc()?lc()->xr:0)^(rc()?rc()->xr:0)^val;
}
bool isroot(){return !fa||(fa->lc()!=this&&fa->rc()!=this);}
bool which(){return fa->rc()==this;}
};
cs int N=300005;
struct Link_Cut_Tree{
point tr[N];
void init(int n){
for(int re i=1;i<=n;++i){
tr[i]=(point)malloc(sizeof(splay_node));
tr[i]->init(getint());
}
}
void Rotate(point now){
point Fa=now->fa,FA=Fa->fa;
bool pos=now->which();
if(FA&&!Fa->isroot())FA->son[Fa->which()]=now;
Fa->son[pos]=now->son[!pos];
if(Fa->son[pos])Fa->son[pos]->fa=Fa;
now->son[!pos]=Fa;
Fa->fa=now;
now->fa=FA;
Fa->pushup();
now->pushup();
}
void Splay(point now){
static point q[N];
static int qn;
q[qn=1]=now;
for(point Fa=now;!Fa->isroot();Fa=Fa->fa)q[++qn]=Fa->fa;
for(int re i=qn;i;--i)q[i]->pushdown();
for(point Fa=now->fa;!now->isroot();Rotate(now),Fa=now->fa)
if(!Fa->isroot())Rotate(now->which()==Fa->which()?Fa:now);
}
void access(point now){
for(point son=NULL;now;son=now,now=now->fa){
Splay(now);now->rc()=son;
now->pushup();
}
}
void makeroot(point now){
access(now);
Splay(now);
now->tag^=1;
}
point findroot(point now){
access(now);
Splay(now);
while(now->lc())now=now->lc();
return now;
}
void link(point u,point v){
makeroot(u);
if(findroot(v)!=u)u->fa=v;
}
void Link(int u,int v){link(tr[u],tr[v]);}
void cut(point u,point v){
if(findroot(u)!=findroot(v))return ;//去掉也能过,那是因为洛谷数据水。。。
makeroot(u);
access(v);
Splay(v);
if(u->rc()!=NULL||u->fa!=v||v->son[!u->which()]!=NULL)return ;
v->lc()=u->fa=NULL;
}
void Cut(int u,int v){cut(tr[u],tr[v]);}
int query(point u,point v){
makeroot(u);
access(v);
Splay(v);
return v->xr;
}
int Query(int u,int v){return query(tr[u],tr[v]);}
void update(point u,int v){
u->val=v;
access(u);
Splay(u);
}
void Update(int u,int v){update(tr[u],v);}
}LCT;
int n,m;
signed main(){
n=getint();
m=getint();
LCT.init(n);
while(m--){
int op=getint(),u=getint(),v=getint();
switch(op){
case 0:outint(LCT.Query(u,v)),pc('\n');break;
case 1:LCT.Link(u,v);break;
case 2:LCT.Cut(u,v);break;
case 3:LCT.Update(u,v);break;
}
}
return 0;
}