1. 程式人生 > >洞穴勘測——LCT模板

洞穴勘測——LCT模板

改了4小時,我果然還是太弱了……

#include<bits/stdc++.h>
using namespace std;
const int maxx=1e4+5;
int c[maxx][2],fa[maxx],Rev[maxx];
int get(int x){
    if(c[fa[x]][1]==x)return 1;
    if(c[fa[x]][0]==x)return 0;
    return -1;
}void rot(int x){
 int f=fa[x],ff=fa[f],l=get(x),r=l^1;
    if(get(f)!=-1)c[ff][c[ff][1]==f]=x;
    fa[c[x][r]]=f; fa[f]=x; fa[x]=ff; 
    c[f][l]=c[x][r]; c[x][r]=f; 
}
 
void pushdown(int x){
	if(Rev[x]){
		Rev[x]=0;
		swap(c[x][0],c[x][1]);
		Rev[c[x][0]]^=1;
		Rev[c[x][1]]^=1;
	}
}
void cle(int x){if(get(x)!=-1)cle(fa[x]);pushdown(x);}
void splay(int x){
    cle(x);
    for(int f=fa[x];get(x)!=-1;rot(x),f=fa[x])
        if(get(f)!=-1)rot(get(x)==get(f)?f:x);
}
void Access(int x){for(int t=0;x;x=fa[t=x])splay(x),c[x][1]=t;}
int Findroot(int x){//找x結點的根 
	Access(x);
	splay(x);
	while(c[x][0]){
		pushdown(x);
		x=c[x][0];
	} 
	return x;
} 
int Evert(int x){//反轉X到根的鏈 
	Access(x);
	splay(x);
	Rev[x]=1;
}
void Cut(int x,int y){
	Evert(x);
	Access(y);
	splay(y);
	fa[x]=c[y][0]=0;
}
void Link(int x,int y){//讓x成為y的新兒子 ,注意x是一個根 
	Evert(y);
	fa[y]=x;
}
int main(){
	char ch[20];
	int x,y,n,m;
	scanf("%d%d",&n,&m);
	while(m--){
		scanf("%s%d%d",ch,&x,&y);
		if(ch[0]=='C')Link(x,y);
		if(ch[0]=='D')Cut(x,y);
		if(ch[0]=='Q'){
			if(Findroot(x)==Findroot(y))printf("Yes\n");
			else printf("No\n");
		}
	}
	return 0;
}