P2147 [SDOI2008]洞穴勘测
https://www.luogu.com.cn/problem/P2147
https://darkbzoj.tk/problem/2049
lct 维护连通性
题面长的恶臭,总结出来就是,给你 \(n\) 个点,一开始每边,后来有加边、断边、查询两点是否联通的操作
断边保证断的边存在,且任意时刻任意两点中至多存在一条路径
至多只有一条路径,说明了这些点构成的是森林(否则有环的话,一定会存在环上两点之间有至少两条路径)
那么直接 lct 正常的连边、断边就行了,数据不合法的情况都不用判
查询是否联通就先把一个点换成跟,找另一个点的跟是不是它就行
#include<cstdio>
#include<algorithm>
#include<iostream>
#include<cmath>
#include<map>
#include<iomanip>
#include<cstring>
#define reg register
#define EN std::puts("")
#define LL long long
inline int read(){
register int x=0;register int y=1;
register char c=std::getchar();
while(c<'0'||c>'9'){if(c=='-') y=0;c=std::getchar();}
while(c>='0'&&c<='9'){x=x*10+(c^48);c=std::getchar();}
return y?x:-x;
}
struct tr{
tr *fa,*son[2];
int tag;
}*null,dizhi[10005],*pos[10005];
#define ident(fa,tree) (fa->son[1]==tree)
#define notroot(tree) (tree->fa->son[0]==tree||tree->fa->son[1]==tree)
inline void pushdown(tr *tree){
if(!tree->tag) return;
std::swap(tree->son[0],tree->son[1]);
tree->son[0]->tag^=1;tree->son[1]->tag^=1;
tree->tag=0;
}
inline void connect(tr *tree,tr *fa,int k){tree->fa=fa;fa->son[k]=tree;}
inline void rotate(tr *tree){
tr *fa=tree->fa,*faa=fa->fa;
pushdown(fa);pushdown(tree);
int k=ident(fa,tree);
connect(tree->son[k^1],fa,k);
tree->fa=faa;
if(notroot(fa)) faa->son[ident(faa,fa)]=tree;
connect(fa,tree,k^1);
}
inline void splay(tr *x){
tr *fa,*faa;
while(notroot(x)){
fa=x->fa;faa=fa->fa;
if(notroot(fa)) rotate(ident(fa,x)^ident(faa,fa)?x:fa);
rotate(x);
}
}
inline void access(tr *x){
for(reg tr *lastx=null;x!=null;lastx=x,x=x->fa){
pushdown(x);splay(x);
x->son[1]=lastx;
}
}
inline tr *findroot(tr *tree){
access(tree);splay(tree);
pushdown(tree);
while(tree->son[0]!=null) tree=tree->son[0],pushdown(tree);
splay(tree);
return tree;
}
inline void makeroot(tr *tree){
access(tree);splay(tree);
tree->tag^=1;
}
inline void link(tr *x,tr *y){
makeroot(x);x->fa=y;
}
inline void cut(tr *x,tr *y){
makeroot(x);
access(y);splay(y);
y->son[0]=x->fa=null;
}
int main(){
int n=read(),m=read();
null=&dizhi[0];
for(reg int i=1;i<=n;i++){
pos[i]=&dizhi[i];
dizhi[i].son[0]=dizhi[i].son[1]=dizhi[i].fa=null;
}
int u,v;reg char op;
while(m--){
op=getchar();
while(op!='C'&&op!='Q'&&op!='D') op=getchar();
u=read();v=read();
if(op=='C') link(pos[u],pos[v]);
else if(op=='D') cut(pos[u],pos[v]);
else{
makeroot(pos[u]);
puts(findroot(pos[v])==pos[u]?"Yes":"No");
}
}
return 0;
}