首先顾名思义,动态树的用处就是让树动起来(有时候也不用动)。
先讲几个动态树的概念:
动态树由两个东西组成:
一个是原图
一个是若干棵splay树(用来记录重链,具体后面讲),我们称其为辅佐树。
单颗splay记录的东西
他其实记录的就是我这一条链的有关信息。
左右儿子的确定是由原树中的深度确定的。也就是说,假如i是j的父亲,在splay中i相对j而言就是左儿子。
动态树的有关操作
动态树的核心操作是access(x)
其意义为在原图中,将x到root的路径标记为一条重链,并对辅佐树进行一定的修改。
过程?
设x为当前节点,nxt为上一个节点(也就是说x由nxt跳来)
先讲x splay到x所属的链的根,那么x的右儿子现在就不属于x的重链了,我们将他分离出去(具体实现见代码)
然后将nxt赋为x的右儿子.
nxt = x,x = x重链的父亲。
然后一直迭代知道将x->root赋为一条重链。
代码十分简单。
处理完access操作之后,动态树也就变得十分简单了。
以下是几个常用的操作:
最常用的就是evert(x) (将x作为原图的根):
Access(x)之后splay(x),并给x打一个翻转标记即可。(不用讲了吧。。)
link(x,y) (x,y原图中在不同树中)
evert(x),evert(y),后splay(y),Par[y] = x,再Access(y)就可以了。
cut(x,y) (x,y原图中属于相邻两个节点)
evert(x),Access(y),Splay(y),将y与其左儿子分离开就好了。
对于询问操作(x,y):
我们先Access(x),可以发现x到root上的节点都在同一条链上了。
我们在Access(y)的过程中:
注意到w跳到所属重链的父亲---〉(w = par[w])时,
若此时,par[w] = 0,即w与根同属一条重链
那么w就是x,y的LCA了!!(显然)
那么此时nxt所属的重链就是w->y的链的信息
w->R_son就是w->x的链的信息。
然后就没然后了。。
动态树说起来好像好简单的样子(实际裸题也十分简单)
今年NOI2014 day1T2就呵呵了。。。
习题集:
spoj OTOCI
spoj DYNALCA,DYNACON1(一直到现在都没过。。)
spoj QTREE1 -> 4
NOI2014 魔幻森林
BJOI2010次小生成树
其实这些都是比较基础的啦。。。
之后要搞的东东->
(能对子树进行操作的动态树,那个叫啥来着。。)
后缀自动机。
AC自动机的DP以及各种各样的扩展。
DP优化。
平面几何。。
叼炸天的数论。。。
弱菜哭倒在地。。。