• 洛谷.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
    ",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
    ",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
    ",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
    ",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;
    }
    
  • 相关阅读:
    CentOS7 设置软件镜像源
    让树莓派自动上报IP地址到邮箱,二代B
    给树莓派安装看门狗的两种方法,二代B
    树莓派(Raspberry Pi)USB无线网卡自动连接,二代B
    升级MAC OX上的Python到3.4
    http 返回码 405 解决方案之一
    CentOS 6.4 SSH 免密码登录
    SVN的Hooks功能--强制添加注释
    PHP开发中,让var_dump调试函数输出更美观 ^_^#
    CentOS 6.4 命令行 安装 VMware Tools
  • 原文地址:https://www.cnblogs.com/SovietPower/p/8615938.html
走看看 - 开发者的网上家园