zoukankan      html  css  js  c++  java
  • [学习笔记]树链剖分

    基本思想

    树链剖分一种对树进行划分的算法,它先通过轻重边剖分将树分为多条链,保证每条边属于且只属于一条链,然后再通过数据结构来维护每一条链。

    一些定义

    树链:树上的路径.

    剖分:把路径分类为重链和轻链.

    重儿子:u的子节点中siz[v]值最大的v.

    轻儿子:u的其它子节点.

    重边:点u与其重儿子的连边.

    轻边:点u与其轻儿子的连边.

    重链:由重边连成的路径.

    轻链:轻边.

    性质

    1. 如果(u,v)为轻边,则siz[v]$ imes$2<siz[u].
    2. 从根到某一点的路径上轻链、重链的个数都不大于log$;$n.
    3. 树剖序其实也可以是dfs序的一种.

    实现

    一些变量:

    f[u]表示u的父亲.

    siz[u]表示以u为根的子树的大小.

    dep[u]表示u的深度(根深度为1).

    top[u]表示u所在的链的顶端节点.

    son[u]表示与u的重儿子.

    重标号:

    p[u]:重标号后u的编号.

    dfs序:dfs的时候先走重边.

    这样可以使得重边的编号是连续的,方便维护.

    • 用两遍dfs求出所需的所有变量以及重标号.
    int f[N],p[N],dep[N],siz[N],son[N],top[N];
    /*top[u]:u所在的链的顶端节点,son[u]:u的重儿子*/
    inline void dfs1(int u){
        int m=0;siz[u]=1;
        for(int i=g[u];i;i=e[i].nxt)
            if(!dep[e[i].to]){
                f[e[i].to]=u;
                dep[e[i].to]=dep[u]+1;
                dfs1(e[i].to);
                siz[u]+=siz[e[i].to];
                if(siz[e[i].to]>m){
                    son[u]=e[i].to;
                    m=siz[e[i].to];
                }
            }
    }
    inline void dfs2(int u,int tp){
        top[u]=tp;p[u]=++cnt;ww[cnt]=w[u];
        if(son[u]) dfs2(son[u],tp);
        for(int i=g[u];i;i=e[i].nxt){
            if(e[i].to!=f[u]&&e[i].to!=son[u])
                dfs2(e[i].to,e[i].to);
        }
    }
    • 访问修改(u,v):

    类似倍增的走法,每次将深度大的往上移,直到u,v属于同一条链.

    inline int sum(int x,int y){
        int ret=0,t;
        while(top[x]!=top[y]){
            if(dep[top[x]]<dep[top[y]]){
                t=x;x=y;y=t;
            }
            ret+=ask(1,p[top[x]],p[x]);
            x=f[top[x]];
        }
        if(p[x]>p[y]){
            t=x;x=y;y=t;
        }
        ret+=ask(1,p[x],p[y]);
        return ret; 
    }
    inline void change(int x,int y,int k){
        int t;
        while(top[x]!=top[y]){
            if(dep[top[x]]<dep[top[y]]){
                t=x;x=y;y=t;
            }
            cover(1,p[top[x]],p[x],k);
            x=f[top[x]];
        }
        if(p[x]>p[y]){
            t=x;x=y;y=t;
        }
        cover(1,p[x],p[y],k);
    }
  • 相关阅读:
    异常、中断、陷阱
    BigDecimal
    事务
    jsp的九大内置对象
    timer和ScheduledThreadPoolExecutor
    关于Python的导入覆盖解决办法
    RTTI
    Golang不会自动把slice转换成interface{}类型的slice
    Python中下划线的5种含义
    Python如何合并两个字典
  • 原文地址:https://www.cnblogs.com/AireenYe/p/6219160.html
Copyright © 2011-2022 走看看