zoukankan      html  css  js  c++  java
  • 树链剖分

    树链剖分

    树链剖分就是将一棵点权树以先遍历重儿子的方式,得到一个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;
    }

     

  • 相关阅读:
    【基础算法】- 全排列
    【基础算法】- 2分查找
    区块链培训
    Static Binding (Early Binding) vs Dynamic Binding (Late Binding)
    test
    No data is deployed on the contract address!
    "throw" is deprecated in favour of "revert()", "require()" and "assert()".
    Variable is declared as a storage pointer. Use an explicit "storage" keyword to silence this warning.
    京都行
    Failed to write genesis block: database already contains an incompatible
  • 原文地址:https://www.cnblogs.com/ganster/p/8429967.html
Copyright © 2011-2022 走看看