title: ‘Link-Cut Tree学习总结’
categories: 算法
date: 2016-1-14 21:30:00
tags: [LCT,算法]
基本思路
LCT是一种用于解决动态树问题的数据结构。大体上的感受,LCT就是树链剖分和Splay的结合版,什么意思呢?因为要动态维护树的结构和树上的信息,所以把维护重边的线段树换成更灵活的Splay。Splay作为辅助树是按深度来维护树上的一条链,就像是维护树上的一个序列一样。
由于本人语文水平有限,讲不太清楚,感觉还是贴上链接会比较好。
具体的操作请看这篇文章:
好文戳这里
畸形写的小说,很有才:
小说戳这里
Code
本人的模板来源于上方的那篇文章,然而我之前的Splay模板太固执打的递归版,所以打LCT时模板就变得又臭又长又慢了,心好累……
注:Haha函数即为Splay函数。
Access
void Cutright(int k){//断开k到根节点路径上的点的原有的偏爱边
if(tr[k].ch[1]){
tr[tr[k].ch[1]].pf=k;
tr[tr[k].ch[1]].fa=0;
tr[k].ch[1]=0;
}
}
void Access(int k){//取出k到根节点的路径
Haha(k); Cutright(k);
while(tr[k].pf){
int u=tr[k].pf;
Haha(u); Cutright(u);
tr[u].ch[1]=k;
tr[k].pf=0; tr[k].fa=u;
Update(u); k=u;
}
}
Beroot
void Beroot(int k){//把k节点变成根节点
Access(k); Haha(k);
tr[k].flip^=1;//取出k到根节点的路径后将这条路径翻转,即让k节点成为深度最低的节点
}
Findroot
int Findroot(int k){//找到k节点所在树的根节点
Access(k); Haha(k);
while(tr[k].ch[0]) k=tr[k].ch[0];
return k;
}
Link
void Link(int x,int y){//连接x和y两个点
int rt1=Find(x),rt2=Find(y);
if(rt1==rt2) return;
Beroot(x); Access(y);
tr[x].pf=y;
}
Cut
void Cut(int x,int y){//删除x和y两个点之间的连边
Beroot(y); Access(x); Haha(x);
tr[x].ch[0]=tr[y].pf=tr[y].fa=0;
Update(x);
}
Find
int Query(int x,int y){//返回x到y的路径上的询问信息
Beroot(x); Access(y); Haha(y);
return tr[y].val;
}