• 树链剖分


    树链剖分

    树链剖分就是将一棵点权树以先遍历重儿子的方式,得到一个dfs序,再对这个dfs序进行操作,与一般的dfs序不同,重链在该dfs序是一个连续不断的区间,该dfs序支持链修改,链查询,子树查询,子树修改,求lca等。在一棵有根树上,我们称一个节点u 的子节点v 为节点u 的重儿子当且仅当v 是所有子节点中大小最大的(如果有多个,则随便选定一个),其余节点称为轻儿子。如果我们对于所有内部节点(有儿子的节点)都选择一个节点作为其重儿子,那么我们就得到了一个轻重链划分,我们称连接节点及其重儿子的边为重边,反之则为轻边,一条由重边组成的链称为重链

    要定义的的东西:

    father[ N ]  :表示一个节点的父亲节点;

    in[ N ] :表示一个节点进dfs序的位置;

    out[  N ] :表示一个节点出dfs序的位置;

    top[ N  ] :表示一个节点只走重链能到达的最高位置;

    son [ N  ] :表示一个节点的重儿子;

    siz[ N ] :表示一个节点的大小(其子树中节点数加上自己);

    dep[ N ] :表示一个节点的深度;

    代码:

     

    void dfs1( int u ) {
    siz[u] = 1;
    for( int t = head[u]; t; t = last[t] ) {
    int v = dest[t];
    if( v == fat[u] ) continue;
    fat[v] = u;
    dep[v] = dep[u]+1;
    dfs(v);
    siz[u] += siz[v];
    if( siz[v] > siz[son[u]] ) son[u] = v;
    }
    }
    dep[1] = 1;
    fat[1] = 1;
    dfs1(1);

     

    void dfs2( int u, int tp ) {
    in[u] = ++idc;
    top[u] = tp;
    if( son[u] ) dfs2( son[u], tp );//遍历重链
    for( int t = head[u]; t; t = last[t] ) {//遍历轻边
    int v = dest[t];
    if( v == fat[u] || v == son[u] ) continue;
    dfs2( v, v );
    }
    }
    idc = 0;
    dfs2(1,1);

    求lca:

    int lca( int u, int v ) {
    while( top[u] != top[v] ) {
    if( dep[top[u]] < dep[top[v]] ) swap(u,v);
    u = fat[top[u]];
    }
    return dep[u] < dep[v] ? u : v;
    }

     

  • 相关阅读:
    Java排序算法总结(转载)
    Java基础—数组(转载)
    Java基础—注解(转载)
    Java基础—枚举
    JVM虚拟机—JVM的类加载机制
    三,memcached服务的两种访问方式
    二,windows下安装memcached服务
    一,memcached的基本概念
    七,apache配置域名
    六,apache修改默认根文件路径
  • 原文地址:https://www.cnblogs.com/ganster/p/8429967.html
Copyright © 2020-2023  润新知