posts - 200,  comments - 0,  trackbacks - 0

BZOJ传送门

洛谷传送门


解析:

这是一道LCTLCT的裸题,却不够板。

思路:

这是LCTLCT的一个经典应用,维护动态树上节点的联通性。
对于基本操作我不再赘述,详见我的LCTLCT模板(暂未更新)。

这道题就讲一讲怎么维护联通性。

由于同一联通块中的节点是由几条被SplaySplay维护的重链所覆盖的,我们判断连通性的时候只需要将一个节点变为该联通子树的根,然后判断另一个节点的SplaySplay根是否是它就行了。


代码:

#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define re register
#define gc getchar
#define pc putchar
#define cs const

inline
int getint(){
	re int num;
	re char c;
	while(!isdigit(c=gc()));num=c^48;
	while(isdigit(c=gc()))num=(num<<1)+(num<<3)+(c^48);
	return num;
}

inline
char getalpha(){
	re char c;
	while(!isalpha(c=gc()));
	return c;
}

typedef struct splay_node *point;
struct splay_node{
	point son[2],fa;
	bool tag;
	void init(){son[0]=son[1]=fa=NULL,tag=0;}
	void pushdown(){
		if(tag){
			if(son[0])son[0]->tag^=1;
			if(son[1])son[1]->tag^=1;
			swap(son[0],son[1]);
			tag=0;
		}
	}
	point &lc(){return son[0];}
	point &rc(){return son[1];}
	bool isroot(){return !fa||(fa->lc()!=this&&fa->rc()!=this);}
	bool which(){return this==fa->son[1];}
};

cs int N=10004;
struct Link_Cut_Tree{
	point tr[N];
	void init(int n){
		for(int re i=0;i<=n;++i)
		tr[i]=(point)malloc(sizeof(splay_node)),
		tr[i]->init();
	}
	
	void Rotate(point now){
		point Fa=now->fa,FA=Fa->fa;
		if(FA&&!Fa->isroot())FA->son[Fa->which()]=now;
		Fa->fa=now;
		now->fa=FA;
		bool pos=now==Fa->lc();
		point tmp=now->son[pos];
		if(tmp)tmp->fa=Fa;
		Fa->son[!pos]=tmp;
		now->son[pos]=Fa;
	}
		
	void Splay(point now){
		static point q[N];
		static int qn;
		q[qn=1]=now;
		for(point Fa=now;!Fa->isroot();Fa=Fa->fa)q[++qn]=Fa->fa;
		for(int re i=qn;i;--i)q[i]->pushdown();
		for(point Fa=now->fa;!now->isroot();Rotate(now),Fa=now->fa)
		if(!Fa->isroot())Rotate(now->which()==Fa->which()?Fa:now);
	}
	
	void access(point now){
		for(point son=NULL;now;son=now,now=now->fa){
			Splay(now);now->rc()=son;
			if(son)son->fa=now;
		}
	}
	
	void makeroot(point now){
		access(now);
		Splay(now);
		now->tag^=1;
	}
	
	point findroot(point now){
		access(now);
		Splay(now);
		while(now->lc())now=now->lc();
		return now;
	}
	
	void link(point u,point v){makeroot(u);u->fa=v;}
	void Link(int u,int v){link(tr[u],tr[v]);}
	
	void cut(point u,point v){
		makeroot(u),access(v);
		Splay(v);
		u->fa=NULL;
		v->lc()=NULL;
	}
	void Cut(int u,int v){cut(tr[u],tr[v]);}
	
	bool connect(point u,point v){
		makeroot(u);
		point tmp=findroot(v);
		return tmp==u;
	}
	bool Connect(int u,int v){return connect(tr[u],tr[v]);}
	
}LCT;
int n,m;
signed main(){
	n=getint(),m=getint();
	LCT.init(n);
	while(m--){
		char op=getalpha();
		int u=getint(),v=getint();
		switch(op){
			case 'C':{
				LCT.Link(u,v);
				break;
			}
			case 'D':{
				LCT.Cut(u,v);
				break;
			}
			case 'Q':{
				puts(LCT.Connect(u,v)?"Yes":"No");
				break;
			}
		}
	}
	return 0;
}
posted on 2018-10-07 12:02  zxyoi_dreamer  阅读(...)  评论(... 编辑 收藏