就是lct,维护一下连通性
维护相通性的时候,可以用并查集维护吧
但也可以通过找根操作来看是否联通
如果x、y在一棵树上,那么x、y他们这棵树不管怎么转,做左边的点一定是一样的
因此findroot时,找到最左边的点,看是否一样
inline int findroot(int x){
access(x);splay(x); //把x转到根
while(ch[x][0]) x=ch[x][0]; //找最左
return x;
}
这道题就是正常lct了…
#include <cstdio>
#include <algorithm>
using namespace std;
#define N 300010
int cnt,n,m,ch[N][2],fa[N],rev[N];
char op[5];
struct node{int x,y;}a[N];
inline bool isroot(int x){return x!=ch[fa[x]][0] && x!=ch[fa[x]][1];}
inline void rotate(int x){
int y=fa[x],z=fa[y],t=ch[y][0]==x;
if(!isroot(y)) ch[z][ch[z][1]==y]=x;
fa[x]=z;fa[y]=x;fa[ch[x][t]]=y;
ch[y][t^1]=ch[x][t];ch[x][t]=y;
}
inline void pushdown(int x){
if(!rev[x]) return;
rev[ch[x][0]]^=1;rev[ch[x][1]]^=1;rev[x]=0;swap(ch[x][0],ch[x][1]);
}
inline void push(int x){
if(!isroot(x)) push(fa[x]);
pushdown(x);
}
inline void splay(int x){
push(x);
while(!isroot(x)){
int y=fa[x];
if(isroot(y)){rotate(x);return;}
if(ch[y][0]==x^ch[fa[y]][0]==y) rotate(x);
else rotate(y);rotate(x);
}
}
inline void access(int x){
int y=0;
while(x){
splay(x);ch[x][1]=y;
y=x;x=fa[x];
}
}
inline void makeroot(int x){
access(x);splay(x);rev[x]^=1;
}
inline void link(int x,int y){
makeroot(x);fa[x]=y;
}
inline void cut(int x,int y){
makeroot(x);access(y);splay(y);
ch[y][0]=fa[x]=0;
}
inline int findroot(int x){
access(x);splay(x);
while(ch[x][0]) x=ch[x][0];
return x;
}
inline void query(int x,int y){
if(findroot(x)==findroot(y)) printf("Yes\n");
else printf("No\n");
}
int main(){
scanf("%d%d",&n,&m);
for(int i=1;i<n;i++){
int x,y;scanf("%d%d",&x,&y);
link(x,y);
}
for(int i=1;i<=m;i++){
int x,y;scanf("%s%d",op,&x);
if(op[0]=='Q'){
scanf("%d",&y);
query(x,y);
}else if(op[0]=='C'){
scanf("%d",&y);
cut(x,y);
a[++cnt].x=x;a[cnt].y=y;
}else link(a[x].x,a[x].y);
}
return 0;
}