原来一直不知道LCT是干什么的。。。只知道是动态树剖。。。(现在看好像也不是那么像了。。。)
核心:用一丛平衡树维护一棵无根树。。。
因为SPLAY与LCT相性最好。。。(个人感觉。。。毕竟还没看到拿TREAP写的。。。(PS:我孤陋寡闻。。。));
所以用SPLAY维护!!!
核心++:把一棵树剖成许多链。。。一条长度为log(n)的链是一棵SPLAY(关键字:dep)
所以SPLAY最左端就是root!!!
#include<cstdio>
#include<iostream>
#define MAXN 10005
using namespace std;
int ch[MAXN][2],fa[MAXN];
int lazy[MAXN],num[MAXN];
inline bool root(int x)
{return ch[fa[x]][0]!=x&&ch[fa[x]][1]!=x;}
void rotate(int x)
{
int y=fa[x],z=fa[y];
int d=ch[y][0]==x ? 0:1;
if(!root(y))
{
if(ch[z][0]==y)ch[z][0]=x;
else ch[z][1]=x;
}
fa[y]=x,fa[x]=z,fa[ch[x][d^1]]=y;
ch[y][d]=ch[x][d^1],ch[x][d^1]=y;
}
inline void down(int x)
{
if(!lazy[x])return ;
lazy[x]^=1,lazy[ch[x][0]]^=1,lazy[ch[x][1]]^=1;
swap(ch[x][0],ch[x][1]);
}
void up(int x) ///注意先把标记传完。。。否则会T。。。不知原因。。。
{
if(!root(x))up(fa[x]);
down(x);
}
void splay(int x)
{
up(x);
int y,z;
while(!root(x))
{
y=fa[x],z=fa[y];
down(y);down(x);
if(!root(y))
{
if((ch[z][0]==y)^(ch[y][0]==x))rotate(x);
else rotate(y);
}
rotate(x);
}
down(x);
}
int pos[MAXN],poi=0;
void access(int x)
{
int t=0;
while(x)
{
splay(x);
ch[x][1]=t;
t=x,x=fa[x];
}
}
void rev(int x)
{
access(x),splay(x);
lazy[x]^=1;
}
void link(int x,int y)
{rev(x);fa[x]=y;}
void cut(int x,int y)
{rev(x),access(y),splay(y),ch[y][0]=fa[x]=0;}
int find(int x)
{
while(fa[x])x=fa[x];
return x;
}
int main()
{
int n,m;
scanf("%d%d",&n,&m);
char opr[10];int t1,t2;
for(int i=1;i<=m;i++)
{
scanf("%s",opr);
scanf("%d%d",&t1,&t2);
if(opr[0]=='C')link(t1,t2);
else if(opr[0]=='D')cut(t1,t2);
else
{
t1=find(t1),t2=find(t2);
if(t1==t2)printf("Yes\n");
else printf("No\n");
}
}
return 0;
}