动态树的一些总结。

动态树这种东西,别人都已经写了几十遍了,我都还以为不会考。感觉自己就是个逗啊。。。


首先顾名思义,动态树的用处就是让树动起来(有时候也不用动)。


先讲几个动态树的概念:

动态树由两个东西组成:

一个是原图

一个是若干棵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赋为一条重链。

代码十分简单。

void access(int x)
{
    int nxt = 0;
    while (x)
    {
        splay(x);
        if (x->R_Son) x->R_Son->fa = 0,Par[x->R_Son] = x;    //Par[x]指的是x所属重链的原图的父亲。
        x->R_Son = nxt;
        if (nxt) nxt->fa = x;
        nxt = x,x = Par[x];
    }
}


处理完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优化。

平面几何。。

叼炸天的数论。。。

弱菜哭倒在地。。。

                           

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值