- 题意:维护森林支持动态插入一条边,删除一条边,查询两点连通性
- 数据范围:100%的数据满足n≤10000, m≤200000
- 题解:LCT模板题,注意link-cut时提根即可
#include <iostream>
#include <cstdio>
#include <cstring>
#define MAXN 21000
using namespace std;
struct node{
node *ch[2],*fa;int num;
int rev;
int dir(){return this==fa->ch[1];}
void cnct(node *p,int d){ch[d]=p;p->fa=this;}
void down();
}tnull,*null=&tnull,*tree[MAXN];
void node::down(){
if(this==null) return;
if(rev){
if(ch[0])ch[0]->rev^=1;
if(ch[1])ch[1]->rev^=1;
swap(ch[0],ch[1]);
rev=0;
}
}
node *getnode(int a){
node *p=new node;
p->fa=p->ch[0]=p->ch[1]=null;p->rev=0;
p->num=a;
}
bool isroot(node *p){
return p==null||p!=p->fa->ch[0]&&p!=p->fa->ch[1];
}
void rotate(node *p){
if(isroot(p)) return;
int f=p->dir();
node *x=p->fa;
if(x==x->fa->ch[0])
x->fa->ch[0]=p;
else if(x==x->fa->ch[1])
x->fa->ch[1]=p;
p->fa=x->fa;
x->cnct(p->ch[!f],f);
p->cnct(x,!f);
}
void splay(node *p){
static node* sta[MAXN];int top=0;
sta[++top]=p;
for(node *k=p;!isroot(k);k=k->fa)
sta[++top]=k->fa;
while(top)
sta[top--]->down();
while(!isroot(p)){
if(isroot(p->fa)) {rotate(p);return;}
else
if(p->dir()==p->fa->dir()) rotate(p->fa),rotate(p);
else rotate(p),rotate(p);
}
}
node *access(node *p){
node *q=null;
while(p!=null){
splay(p);
p->cnct(q,1);
q=p;
p=p->fa;
}
return q;
}
void mtr(node *p){
access(p);
splay(p);
p->rev=1;
}
void link(node *p,node *q){
mtr(p);
p->fa=q;
}
void cut(node *p,node *q){
mtr(p);
access(q);
splay(q);
q->ch[0]=q->ch[0]->fa=null;
}
node* getroot(node *p){
while(p->fa!=null)
p=p->fa;
return p;
}
int n,m;
char c[100];
int main(){
while(~scanf("%d%d",&n,&m)){
for(int i=1;i<=n;i++)
tree[i]=getnode(i);
for(int i=1;i<=m;i++){
int a,b;scanf("%s",c);
scanf("%d%d",&a,&b);
if(c[0]=='Q')
if(getroot(tree[a])!=getroot(tree[b]))
puts("No");
else
puts("Yes");
else if(c[0]=='C')
link(tree[a],tree[b]);
else
cut(tree[a],tree[b]);
}
}
return 0;
}