题意
一颗树支持:
- 连接两个点
- 删除两个点之间的边
- 询问两个点是否连通
分析
第一次做LCT的题,有点小激动,虽然这只是一道模板题而已。
由题意可知我们需要进行三个操作:link,cut,query
对于连接(x,y)这条边,我们先 makeroot(x) ,再将 x 的 fa 置为 y
删除的话,先makeroot(x),再access(y)【取出 y 到 x 的这条路径,且当前状态下这条路径上只有 x 和 y 】,splay(y)
然后将 lc(y) = 0; fa(x) = 0;
询问的话就更简单了,直接比较 x 和 y 所在树的根节点是否相同
小小牢骚
一下午的调试很崩溃啊
- 用宏命令,小括号太多,手贱,打错了一个
- 在splay的时候忘记更新fa的值了
- rotate的时候顺序有bug
(这是拿命在调代码啊!!!,感谢zxy大佬Orz,感谢dzy大佬Orz)
如果要别人帮忙调代码的话,真的很麻烦人家,希望自己可以自己多想想,别老是麻烦人家
调试心得:
最好不要用宏命令,特别是带括号的那一种,不然完全分不清是函数还是什么鬼啊,而且一不小心手滑,括号就出锅了,而且根本检查不出来啊
代码
//虽然我很菜,但我也会很努力!
#include<bits/stdc++.h>
#define in read()
#define N 10009
#define M 400009
using namespace std;
inline int read(){
char ch;int f=1,res=0;
while((ch=getchar())<'0'||ch>'9') if(ch=='-') f=-1;
while(ch>='0'&&ch<='9'){
res=(res<<3)+(res<<1)+ch-'0';
ch=getchar();
}
return f==1?res:-res;
}
int n,m,u,v,que[N],qr=0;
char st[10];
struct node{
int lc,rc,fa,lzy;
#define fa(x) p[x].fa
#define lc(x) p[x].lc
#define rc(x) p[x].rc
#define lzy(x) p[x].lzy
}p[N];
void pushdown(const int &k){
if(lzy(k)){
swap(lc(k),rc(k));
lzy(lc(k))^=1;
lzy(rc(k))^=1;
lzy(k)=0;
}
return ;
}
bool isroot(const int &x){
if(!fa(x)) return 1;
if((lc(fa(x))!=x)&&(rc(fa(x))!=x)) return 1;//括号出锅
return 0;
}
void rotate(const int &x){
int y=fa(x),z=fa(y),a=(lc(y)==x)?rc(x):lc(x);
if(z&&!isroot(y)) ((lc(z)==y)?lc(z):rc(z))=x;
fa(x)=z;fa(y)=x;
if(a) fa(a)=y;
if((lc(y)==x)) rc(x)=y,lc(y)=a;
else lc(x)=y,rc(y)=a;
return ;
}
void splay(const int &x){// 由于打了标记,因此根到当前需要Splay 的节点的路径上的标记需要全部下放
que[qr=0]=x;
for(int y=x;!isroot(y);y=fa(y)) que[++qr]=fa(y);
for(int i=qr;i>=0;--i) pushdown(que[i]);//pushdown!!!
int y=fa(x),z=fa(y);
while(!isroot(x)){
y=fa(x),z=fa(y);//更新
if(!isroot(y)){
if((x==lc(y))==(y==lc(z))) rotate(y);
else rotate(x);
}
rotate(x);//
}
return ;
}
void access(int x){
for(int y=0;x;y=x,x=fa(x)){
splay(x);rc(x)=y;
}
return ;
}
void makeroot(const int &x){
access(x);splay(x);
lzy(x)^=1;return;
}
void link(const int &x,const int &y){
makeroot(x);fa(x)=y;
return;
}
void cut(const int &x,const int &y){
makeroot(x);access(y);splay(y);
lc(y)=0;fa(x)=0;
return;
}
int findroot(int x){
access(x);splay(x);//after every operation u have to splay
while(pushdown(x),lc(x)) x=lc(x);
return x;
}
int main(){
n=in;m=in;
while(m--){
scanf("%s",st);
u=in;v=in;
if(st[0]=='C') link(u,v);
else{ if(st[0]=='D') cut(u,v);
else {
if(findroot(u)==findroot(v)) printf("Yes\n");
else printf("No\n");
}
}
}
return 0;
}