suxxsfe

一言(ヒトコト)

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;
}
posted @ 2020-08-10 11:12  suxxsfe  阅读(86)  评论(0编辑  收藏  举报