zoukankan      html  css  js  c++  java
  • LCT学习笔记

    link-cut-tree 是一种维护森林的数据结构,可以在log的时间内完成修改、查询链上信息等操作 。

    实链剖分

    我们知道,树链剖分通过划分轻重链,保证了一个点到根最多有log跳轻链和log条重链从而保证复杂度为log。

    而LCT通过把每条边划分成实边和虚边,把整棵树拆成若干部分,每部分在原树中是深度严格递增的一条链(相当于是自上而下的一条链)。

    而我们的每一部分都是用splay去维护的,而在每棵splay中点的深度也是严格递增的。

    对于每一条实边,父亲都有连向儿子的一条边,儿子也有连向父亲的边。

    对于每一条虚边,只有儿子连向父亲的边。

    下面我们了解一下LCT的各种操作。

    access

    我们定义access(x)为,打通一条从x到整颗树的根的一条实链。

    打通之后,x所在的splay中只有x到根这条链上的的所有点。

    首先我们明确,对于一颗splay中某个点x,ch[x][0]中所有点的深度都是比它小的,ch[x][1]中所有点的深度都是比它大的。

    若fa[x]=y那么y的深度一定比x小。

    那么首先我们把x splay一下,然后我们把它的右儿子断成虚边,因为这部分我们不希望它出现在最后的splay里(因为x要成为splay里深度最大的点)。

    然后我们把指针指向fa[x],令其为y,我们再去splay(y),这是我们也需要把y的右儿子断掉,然后向x连一条重边。

    然后上述过程一直重复就好了,代码如下。

    inline void access(int x){
        for(int y=0;x;y=x,x=fa[x])splay(x),ch[x][1]=y,pushup(x);
    }

    makeroot

    我们定义makeroot(x)为把x当做整颗splay的根。

    首先我们肯定要access(x),让它和根在一颗splay里。

    考虑x成为根之后,整棵树相对深度发生变化的点只存在于这颗splay中,而且相对深度和原来是完全相反的,所以我们只需要在splay(x),使x成为根节点后reverse整颗splay就好了。

    代码长这样:

    inline void makeroot(int x){access(x);splay(x);rev[x]^=1;}

    split

    我们定义split(x,y)为找到x到y的一条路径。

    如果上面的东西都理解了,这个就好说了。

    inline void split(int x,int y){
        makeroot(x);access(y);splay(y);
    }

    findroot

    我们定义findroot(x)为找到x所在树的根。

    我们先access一下,在splay一下,因为根是整颗splay里深度最浅的点,所以我们一直往左儿子找就好了。

    注意pushdown

    inline int findroot(int x){
        access(x);splay(x);pushdown(x);
        while(ch[x][0])x=ch[x][0],pushdown(x);
        return x;
    }

    link

    我们定义link(x,y)为连接一条x到y的虚边。

    我们先makeroot x,直接令fa[x]=y即可,不难理解。

    注意判不合法情况

    inline void link(int x,int y){
        if(findroot(x)===findroot(y))return;
        makeroot(x);fa[x]=y;
    }

    cut

    我们定义cut(x,y)为切断x到y的边。

    我们先split出x到y的链。

    然后我们要判断当前是否存在x到y的边。

    令x为根,y为splay的根,那么ch[y][0]=x,ch[y][1]=0,fa[x]=y若三个条件同时满足那么我们可以切断这条边 。

    inline void cut(int x,int y){
        if(findroot(x)!=findroot(y))return;
        split(x,y);
        if(fa[x]!=y||ch[y][1]||ch[y][0]!=x)return;
        fa[x]=ch[y][0]=0;
    }

    LCT的概念和基本操作就是这么多,感觉这里面也有很多十分玄妙的地方,不过感性理解就好了。

    未完待续。。。

  • 相关阅读:
    shell编程基础
    centos7怎么查看、打开和关闭防火墙
    Linux下查看根目录各文件内存占用情况
    两台Linux系统之间传输文件的几种方法
    rabbitmq3.8版本默认用户guest访问报错User can only log in via localhost解决方案
    docker 部署java web应用_使用Docker部署JavaWeb项目
    ubuntu安装curl命令
    docker重新进入容器时“/etc/profile”中环境变量失效问题的解决
    在docker容器中安装软件,并重新生成镜像
    CentOS7安装RabbitMQ
  • 原文地址:https://www.cnblogs.com/ZH-comld/p/10121523.html
Copyright © 2011-2022 走看看