Link-Cut Tree

概述.

LCT是一种支持动态维护树上路径信息的数据结构,其本质是实链剖分,通过其他数据结构维护实链的信息达到维护路径及一些子树信息的效果(通常为splay)

刚开始学的时候感觉很难,但做过几道题了解套路之后感觉还是一个很良心实用的东西QAQ。

实链剖分.

重链剖分把子树大小作为标准,子树结点个数最多的儿子作为重儿子。

长链剖分把子树深度作为大小,子树深度最大的儿子作为重儿子。

而实链剖分类似,但它的选择方式是动态的,相当于动态地把某些边设为实边,其他为虚边,并维护实链的信息,从而达到维护路径信息的效果。

LCT的实现.

Access是LCT的核心操作,它的作用是把某一个结点x到根的路径设为实链,并将x的儿子连向x的边设为虚边,相当于制造了一个只包含根到x的路径的实链。

这一操作可以通过不断splay来实现。

而实现了Access之后LCT的其他操作就能够轻松地实现了(详见下面的代码)。

struct Link_Cut_Tree {
	int ch[MAXN][2],rev[MAXN],size[MAXN],s[MAXN],fa[MAXN],a[MAXN],stk[MAXN],sz=0;
	void Clear(int x)   { rev[x]=ch[x][0]=ch[x][1]=fa[x]=a[x]=0; }
	void Update(int x)  { if (!x)      return; s[x]=a[x]^s[ch[x][0]]^s[ch[x][1]];      } 
	void Rev(int x)     { if (!x)      return; rev[x]^=1; swap(ch[x][0],ch[x][1]);     }
	void Pushdown(int x){ if (!rev[x]) return; Rev(ch[x][0]); Rev(ch[x][1]); rev[x]=0; }
	bool Isroot(int x)  { return ch[fa[x]][1]!=x&&ch[fa[x]][0]!=x; }
	int Get(int x)      { return ch[fa[x]][1]==x; }
	void Rotate(int x)  {
		int father=fa[x],grandfa=fa[father],which=Get(x);
		if (!Isroot(father)) ch[grandfa][Get(father)]=x;fa[x]=grandfa;
		ch[father][which]=ch[x][which^1],fa[ch[father][which]]=father;
		ch[x][which^1]=father,fa[father]=x;
		Update(father),Update(x);
	}
	void Splay(int x) { 
		int top=1; stk[top]=x;
		for (int p=x;!Isroot(p);p=fa[p]) stk[++top]=fa[p];
		while (top) Pushdown(stk[top--]);
		for (int father;father=fa[x],!Isroot(x);Rotate(x)) 
			if (!Isroot(father)) Rotate(Get(x)==Get(father)?father:x);
	}
	void Access(int x)     { for (int p=0;x;p=x,x=fa[x]) Splay(x),ch[x][1]=p,Update(x); }
	void Make_root(int x)  { Access(x),Splay(x),Rev(x); };
	int  Find_root(int x)  { Access(x),Splay(x); while (ch[x][0]) Pushdown(x),x=ch[x][0]; Splay(x); return x; }
	void Split(int x,int y){ Make_root(x),Access(y),Splay(y); }
	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[y]!=x||ch[y][0]) return; fa[y]=ch[x][1]=0,Update(x); }
	int Query_Xor(int x,int y) { Split(x,y); return s[y]; }
} lct;

LCT的应用.

目前只在某谷上做了一些比较容易的题,之后再补充吧。

维护动态连通性:

  • P3690 【模板】Link Cut Tree (动态树)
  • P2147 [SDOI2008]洞穴勘测

动态维护生成树:

  • P4234 最小差值生成树
  • P2387 [NOI2014]魔法森林

类似LCT:

  • P4338 [ZJOI2018]历史

一点总结.

与其说LCT是一种数据结构,不如说LCT是一种维护树上数据的思想(实链剖分),它的时间复杂度  O(nlgn) 比树链剖分更加优秀,并支持动态维护树形结构,并且理解上不算困难,只要熟练掌握Splay就能轻松学会LCT了。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值