博客园 首页 私信博主 显示目录 隐藏目录 管理 动画

洛谷.3690.[模板]Link Cut Tree(动态树)

题目链接

LCT(良心总结)

#include <cstdio>
#include <cctype>
#include <algorithm>
#define gc() getchar()
const int N=3e5+5;

inline int read()
{
	int now=0;register char c=gc();
	for(;!isdigit(c);c=gc());
	for(;isdigit(c);now=now*10+c-'0',c=gc());
	return now;
}
namespace LCT
{
	#define lson son[x][0]
	#define rson son[x][1]

	int fa[N],val[N],sum[N],son[N][2],sk[N];
	bool tag[N];
	inline void Update(int x){
		sum[x]=sum[lson]^sum[rson]^val[x];
	}
	inline void Rev(int x){
		std::swap(lson,rson), tag[x]^=1;
	}
	inline void PushDown(int x){
		if(tag[x]) Rev(lson),Rev(rson),tag[x]=0;
	}
	inline bool n_root(int x){
		return son[fa[x]][0]==x||son[fa[x]][1]==x;
	}
	void Rotate(int x)
	{
		int a=fa[x],b=fa[a],l=son[a][1]==x,r=l^1;
		if(n_root(a)) son[b][son[b][1]==a]=x;
		if(son[x][r]) fa[son[x][r]]=a;
		fa[a]=x, fa[x]=b;
		son[a][l]=son[x][r], son[x][r]=a;
		Update(a), Update(x);
	}
	void Splay(int x)
	{
		int t=1,a=x,b; sk[1]=x;
		while(n_root(a)) sk[++t]=a=fa[a];//别写成while(fa[x])!
		while(t) PushDown(sk[t--]);
		while(n_root(x))
		{
			a=fa[x], b=fa[a];
			if(n_root(a)) Rotate(son[a][1]==x^son[b][1]==a?x:a);
			Rotate(x);
		}
		Update(x);//还是加上吧 
	}
	void Access(int x){
		for(int pre=0; x; x=fa[pre=x])//pre=x老漏。。
			Splay(x), rson=pre, Update(x);
	}
	void Make_root(int x){
		Access(x), Splay(x), Rev(x);
	}
	void Split(int x,int y){
		Make_root(x), Access(y), Splay(y);
	}
	int Find_root(int x)
	{
		Access(x), Splay(x);
		while(lson) x=lson;
//		Splay(x);//需要保证复杂度?
		return x;
	}
//	int Get_fa(int x){
//		while(fa[x]) x=fa[x];
//		return x;
//	}
//	void Link(int x,int y){
//		if(Get_fa(x)!=Get_fa(y)) Make_root(x),fa[x]=y;//Get_fa()有点慢啊 
//	}
	void Link(int x,int y)
	{
		Make_root(x);
		if(Find_root(y)!=x) fa[x]=y;//连的是轻边!不要加rson=y;
	}
	void Cut(int x,int y)
	{
		Make_root(x);
		if(Find_root(y)==x&&fa[x]==y&&!rson)
			fa[x]=son[y][0]=0, Update(y);
//		if(Find_root(y)==x&&fa[y]==x&&!son[y][0])//若Find_root()中把根又转回去了 
//			fa[y]=rson=0, Update(x);
	}
}

int main()
{
	int n=read(),m=read();
	for(int i=1; i<=n; ++i) LCT::val[i]=read();
	int opt,x,y;
	while(m--)
	{
		opt=read(),x=read(),y=read();
		if(!opt) LCT::Split(x,y), printf("%d\n",LCT::sum[y]);
		else if(opt==1) LCT::Link(x,y);
		else if(opt==2) LCT::Cut(x,y);
		else LCT::Splay(x), LCT::val[x]=y;/*sum[y]^=val[x]^y, val[x]=y*/ //这步在Split()(查询时)的Splay()中 最后还会Update() 
	}
	return 0;
}

第二次(2018.4.5):

#include <cstdio>
#include <cctype>
#include <algorithm>
#define gc() getchar()
const int N=3e5+5;

inline int read()
{
	int now=0;register char c=gc();
	for(;!isdigit(c);c=gc());
	for(;isdigit(c);now=now*10+c-'0',c=gc());
	return now;
}
namespace LCT
{
	#define lson son[x][0]
	#define rson son[x][1]

	int fa[N],son[N][2],sum[N],val[N],sk[N];
	bool rev[N];
	inline void Update(int x){
		sum[x]=sum[lson]^sum[rson]^val[x];
	}
	inline bool n_root(int x){
		return son[fa[x]][0]==x||son[fa[x]][1]==x;
	}
	inline void Rev(int x){
		std::swap(lson,rson), rev[x]^=1;
	}
	inline void PushDown(int x){
		if(rev[x]) Rev(lson),Rev(rson),rev[x]=0;
	}
	void Rotate(int x)
	{
		int a=fa[x],b=fa[a],l=son[a][1]==x,r=l^1;
		if(n_root(a)) son[b][son[b][1]==a]=x;
		if(son[x][r]) fa[son[x][r]]=a;
		fa[a]=x, fa[x]=b, son[a][l]=son[x][r], son[x][r]=a;
		Update(a);
	}
	void Splay(int x)
	{
		int t=1,a=x; sk[1]=x;
		while(n_root(a)) sk[++t]=a=fa[a];
		while(t) PushDown(sk[t--]);
		while(n_root(x))
		{
			if(n_root(a=fa[x])) Rotate(son[a][1]==x^son[fa[a]][1]==a?x:a);
			Rotate(x);
		}
		Update(x);
	}
	void Access(int x){
		for(int pre=0; x; x=fa[pre=x])
			Splay(x), rson=pre, Update(x);
	}
	void Make_root(int x){
		Access(x), Splay(x), Rev(x);
	}
	void Split(int x,int y){
		Make_root(x), Access(y), Splay(y);
	}
	int Find_root(int x)
	{
		Access(x), Splay(x);
		while(lson) x=lson;
		return x;
	}
	void Link(int x,int y)
	{
		Make_root(x);
		if(Find_root(y)!=x) fa[x]=y;
	}
	void Cut(int x,int y)
	{
		Make_root(x);
		if(Find_root(y)==x&&fa[x]==y&&!rson)
			fa[x]=son[y][0]=0, Update(y);
	}
}
using namespace LCT;

int main()
{
	int n=read(),m=read(),opt,x,y;
	for(int i=1; i<=n; ++i) val[i]=read();
	while(m--)
		switch(opt=read(),x=read(),y=read(),opt)
		{
			case 0: Split(x,y),printf("%d\n",sum[y]); break;
			case 1: Link(x,y); break;
			case 2: Cut(x,y); break;
			case 3: Splay(x), val[x]=y; break;
		}
	return 0;
}

第三次(2018.6.28):竟然快了那么多,好像没什么太大变化啊。。

//592ms	3.76MB
#include <cstdio>
#include <cctype>
#include <algorithm>
//#define gc() getchar()
#define MAXIN 150000
#define gc() (SS==TT&&(TT=(SS=IN)+fread(IN,1,MAXIN,stdin),SS==TT)?EOF:*SS++)
const int N=3e5+5;

char IN[MAXIN],*SS=IN,*TT=IN;
namespace LCT
{
	#define lson son[x][0]
	#define rson son[x][1]
	int fa[N],son[N][2],val[N],sum[N],sk[N];
	bool rev[N];

	inline void Update(int x){
		sum[x]=sum[lson]^sum[rson]^val[x];
	}
	inline void Rev(int x){
		std::swap(lson,rson), rev[x]^=1;
	}
	inline void PushDown(int x){
		if(rev[x]) Rev(lson), Rev(rson), rev[x]=0;
	}
	inline bool n_root(int x){
		return son[fa[x]][0]==x||son[fa[x]][1]==x;
	}
	void Rotate(int x)
	{
		int a=fa[x],b=fa[a],l=son[a][1]==x,r=l^1;
		if(n_root(a)) son[b][son[b][1]==a]=x;
		if(son[x][r]) fa[son[x][r]]=a;
		fa[x]=b, fa[a]=x, son[a][l]=son[x][r], son[x][r]=a;
		Update(a);
	}
	void Splay(int x)
	{
		int a=x,t=1; sk[1]=x;
		while(n_root(a)) sk[++t]=a=fa[a];
		while(t) PushDown(sk[t--]);
		while(n_root(x))
		{
			if(n_root(a=fa[x])) Rotate(son[a][1]==x^son[fa[a]][1]==a?x:a);
			Rotate(x);
		}
		Update(x);
	}
	void Access(int x){
		for(int pre=0; x; x=fa[pre=x])
			Splay(x), rson=pre, Update(x);		
	}
	void Make_root(int x){
		Access(x), Splay(x), Rev(x);
	}
	void Split(int x,int y){
		Make_root(x), Access(y), Splay(y);
	}
	int Find_root(int x)
	{
		Access(x), Splay(x);
		while(lson) x=lson;
		return x;
	}
	void Link(int x,int y)
	{
		Make_root(x);
		if(Find_root(y)!=x) fa[x]=y;
	}
	void Cut(int x,int y)
	{
		Make_root(x);
		if(Find_root(y)==x&&!rson&&fa[x]==y) son[y][0]=fa[x]=0, Update(y);
	}
}
using namespace LCT;

inline int read()
{
	int now=0;register char c=gc();
	for(;!isdigit(c);c=gc());
	for(;isdigit(c);now=now*10+c-'0',c=gc());
	return now;
}

int main()
{
	int n=read(), m=read();
	for(int i=1; i<=n; ++i) val[i]=read();
	int opt,x,y;
	while(m--){
		switch(opt=read(),x=read(),y=read(),opt){
			case 0: Split(x,y), printf("%d\n",sum[y]); break;
			case 1: Link(x,y); break;
			case 2: Cut(x,y); break;
			case 3: Splay(x), val[x]=y; break;
		}
	}
	return 0;
}

19.4.5

//520ms	2984KB
#include <cstdio>
#include <cctype>
#include <algorithm>
#define gc() getchar()
#define MAXIN 300000
//#define gc() (SS==TT&&(TT=(SS=IN)+fread(IN,1,MAXIN,stdin),SS==TT)?EOF:*SS++)
typedef long long LL;
const int N=3e5+5;

char IN[MAXIN],*SS=IN,*TT=IN;
struct LCT
{
	#define ls son[x][0]
	#define rs son[x][1]
	int fa[N],son[N][2],sum[N],val[N],sk[N];
	bool rev[N];
	inline void Update(int x)
	{
		sum[x]=sum[ls]^sum[rs]^val[x];
	}
	inline bool n_root(int x)
	{
		return son[fa[x]][0]==x||son[fa[x]][1]==x;
	}
	inline void Rev(int x)
	{
		std::swap(ls,rs), rev[x]^=1;
	}
	inline void PushDown(int x)
	{
		if(rev[x]) Rev(ls), Rev(rs), rev[x]=0;
	}
	void Rotate(int x)
	{
		int a=fa[x],b=fa[a],l=son[a][1]==x,r=l^1;
		if(n_root(a)) son[b][son[b][1]==a]=x;
		if(son[x][r]) fa[son[x][r]]=a;
		fa[x]=b, fa[a]=x, son[a][l]=son[x][r], son[x][r]=a;
		Update(a);
	}
	void Splay(int x)
	{
		int t=1,a=x; sk[1]=a;
		while(n_root(a)) sk[++t]=a=fa[a];
		while(t) PushDown(sk[t--]);
		while(n_root(x))
		{
			if(n_root(a=fa[x])) Rotate(son[a][0]==x^son[fa[a]][0]==a?x:a);
			Rotate(x);
		}
		Update(x);
	}
	void Access(int x)
	{
		for(int pre=0; x; x=fa[pre=x])
			Splay(x), rs=pre, Update(x);
	}
	void MakeRoot(int x)
	{
		Access(x), Splay(x), Rev(x);
	}
	void Split(int x,int y)
	{
		MakeRoot(x), Access(y), Splay(y);
	}
	int FindRoot(int x)
	{
		Access(x), Splay(x);
		while(ls) x=ls;
		return x;
	}
	void Link(int x,int y)
	{
		MakeRoot(x);
		if(FindRoot(y)!=x) fa[x]=y;
	}
	void Cut(int x,int y)
	{
		MakeRoot(x);
		if(FindRoot(y)==x&&fa[x]==y&&!rs) fa[x]=son[y][0]=0, Update(y);
	}
}T;

inline int read()
{
	int now=0;register char c=gc();
	for(;!isdigit(c);c=gc());
	for(;isdigit(c);now=now*10+c-48,c=gc());
	return now;
}

int main()
{
	int n=read(),q=read();
	for(int i=1; i<=n; ++i) T.val[i]=read();
	for(int x,y; q--; )
		switch(read())
		{
			case 0: x=read(),y=read(),T.Split(x,y),printf("%d\n",T.sum[y]); break;
			case 1: x=read(),y=read(),T.Link(x,y); break;
			case 2: x=read(),y=read(),T.Cut(x,y); break;
			case 3: T.Splay(x=read()),T.val[x]=read(); break;
		}

	return 0;
}
posted @ 2018-03-21 11:21  SovietPower  阅读(214)  评论(1编辑  收藏  举报