Link-Cut Tree
概述.
LCT是一种支持动态维护树上路径信息的数据结构,其本质是实链剖分,通过其他数据结构维护实链的信息达到维护路径及一些子树信息的效果(通常为splay)
刚开始学的时候感觉很难,但做过几道题了解套路之后感觉还是一个很良心实用的东西QAQ。
实链剖分.
重链剖分把子树大小作为标准,子树结点个数最多的儿子作为重儿子。
长链剖分把子树深度作为大小,子树深度最大的儿子作为重儿子。
而实链剖分类似,但它的选择方式是动态的,相当于动态地把某些边设为实边,其他为虚边,并维护实链的信息,从而达到维护路径信息的效果。
LCT的实现.
Access是LCT的核心操作,它的作用是把某一个结点到根的路径设为实链,并将的儿子连向的边设为虚边,相当于制造了一个只包含根到的路径的实链。
这一操作可以通过不断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是一种维护树上数据的思想(实链剖分),它的时间复杂度 比树链剖分更加优秀,并支持动态维护树形结构,并且理解上不算困难,只要熟练掌握Splay就能轻松学会LCT了。