Link Cut Tree学习小记
2016-09-03 16:09
323 查看
前言
其实我早就知道Link Cut Tree 是什么东东,可是懒癌晚期不想仔细学。简单点说就是动态的树链剖分,因为我们链剖用的是线段树,死在那里。
既然要用动态,那么肯定要用平衡树来维护啦,我们选择splay。
如果不会splay的还是别看了,splay学习小记
一些东西
其实这个东西杨哲的集训队作业也是有的,大家可以先去看一看。我们把之前访问到的点称作偏爱点,从根到偏爱点的路径叫做偏爱路径。偏爱路径上的边叫做偏爱边。每个点向它的儿子只会连一条偏爱边。
我们用splay维护所有的偏爱路径,这样就形成了一片森林。
splay中点x保证左节点的深度小于x,右节点的深度大于x。
然后,对于每个splay中的根,它在原树中往上第一条不是偏爱边所连向的点叫做它的Path Parent,连接这两个点的边叫做Path Parent边。
这样就形成了一棵LinkCutTree。
盗图狗路过
功能
要实现LinkCutTree的功能,我们就必须让那些点在同一棵splay上。也就是说,我们需要用access(x)来把原树的根到x点的路径上所有的边变成偏爱边。
void access(int x){ int y=0; while(x){ splay(x,0); f[t[x][1]]=0,pfa[t[x][1]]=x; t[x][1]=y,f[y]=x; pfa[y]=0; update(x); y=x,x=pfa[x]; } }
其实就是沿着path parent边往上跳。
为什么要把右边断掉?
因为根到x中的点的深度都比x小,比x大的就不在偏爱路径上了。
这个操作是LinkCutTree的核心。
不过注意,执行splay操作的时候可能会改变pfa(因为这一棵splay的根改变了),所以旋转的时候要注意。
那些要维护的值就和普通splay一样维护就可以了。
接下来要讲的就是关于动态树的动态操作
换根
void makeroot(int x) { access(x);splay(x,0);rev[x]^=1; }
这里就是我们要选用splay的原因。
因为我们有翻转操作。
为什么呢?
因为splay是按深度来建的,把x换到根之后,1~x的深度全部翻转了。
连边
void link(int x,int y) { makeroot(x);p[x]=y; }
很显然吧。
删边
void cut(int x,int y) { makeroot(x);access(y);splay(y,0); t[y][0]=0;f[x]=p[x]=0; updata(y); }
这个比较巧妙。
先把x换到根,然后把x到y的路径改成偏爱路径。
这样x和y就在同一棵splay上了。且x比y的深度小。
如果把y splay上去,x就会在y的左边。
断掉就好了。
求x到y的路径
makeroot(x);access(y);splay(y,0);
这样y点的值就是x到y的路径上的值。
原因一样。
然后这些就够用了吧。
哦,还有一点。
如何用LinkCutTree维护边权?
一个直观的想法是把每个点的点权设为它父边的边权。
但是这样很明显会错。
因为在access操作中树的形态会改变。
那么怎么办呢?
某神犇:把每条边看成点,维护点权就好了
肿么就辣么机智勒。
相关文章推荐
- link cut tree学习小记
- 【动态树之link_cut_tree学习小记】
- Link Cut Tree学习小记
- NOI级别的超强数据结构——Link-cut-tree(动态树)学习小记(update guadually...)
- Link Cut Tree学习小记
- Link cut tree学习笔记
- [Link-Cut-Tree]【学习笔记】
- 【学习】动态树 link cut tree
- LCT (Link-Cut-Tree) 学习笔记
- LCT(Link-Cut-Tree)学习
- Link Cut Tree(LCT )学习笔记
- 算法学习之:动态树(link-cut-tree)及bzoj3282Tree例题详解
- 学习一个LinkCutTree
- Link-cut-tree 学习记录 & hdu4010
- Link-Cut-Tree 学习笔记
- Link Cut Tree学习笔记
- bzoj 2002 LinkCutTree
- BZOJ 2594 Wc2006 水管局长数据加强版 Link-Cut-Tree
- BZOJ 2555 Substring 后缀自动机+Link-Cut-Tree
- BZOJ2157【Link Cut Tree】