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

     

    将树分割成多条链,然后用线段树等来维护这些链。

    树链剖分的分割标准:连接一个节点的子树中的 “ 重儿子 ” // 也就是结点最多的儿子,依次连下去。

    实现

    定义:

    重儿子:子树节点的儿子

    轻儿子:除了重儿子以外的儿子

    重边:父节点与重儿子组成的边

    轻边:除重边以外的边

    重链:重边连接而成的链

    轻链:轻边连接而成的链

    链头:一条链上深度最小的点

     

    对于树链剖分,我们需要维护以下的数组:

    名称含义
    siz[u] 保存以u为根的子树节点个数
    son[u] 保存u的重儿子
    top[u] 保存u所在链的顶端节点
    dep[u] 保存结点u的深度值
    faz[u] 保存结点u的父亲节点
    dfn[u] u的DFS序
    rk[u] u树中的编号

     

    DFS_1:预处理 siz, son, dep, faz数组

     void Dfs1(int u, int father, int depth)
     {
         dep[u] = depth;
         faz[u] = father;
         siz[u] = 1;
         
         for(int i = head[u]; i; i = edge[i].next)
         {
             int v = edge[i].to;
             // 如果连接的结点是当前结点的父亲结点,则不处理
             if(v != faz[u])
             {
                 Dfs1(v,u,depth+1);
                 siz[u] += siz[v];
                 if(son[u] == -1 || siz[v] > siz[son[u]])
                     son[u] = v;
             }
         }
         return;
     }

    DFS_2:预处理dfn, top, rk 数组。

     void Dfs2(int u, int t) // t:起始的重节点
     {
         top[u] = t;
         dfn[u] = cnt;
         rk[cnt] = u;
         cnt++;
         
         if(son[u] == -1) return;
         Dfs2(son[u], t);
         
         for(int i = head[u]; i; i = edge[i].next)
         {
             int v = edge[i].to;
             if(v != son[u] && v != faz[u])
                 Dfs2(v,v);
         }
         return;
     }

    维护

    修改:

     void modifyOnTree(int u, int v, int val)
     {
         // 更新节点 u 到节点 v 的值
         while(top[u] != top[v])
         {
             // 不妨设dep[top[u]] > dep[top[v]]
             if(dep[top[u]] < dep[top[v]]) swap(u,v);
             Modify(1, 1, n, dfn[top[u]], dfn[u], val);
             u=faz[top[u]];
         }
         if(dep[u] > dep[v]) swap(u,v);
         Modify(1, 1, n, dfn[u], dfn[v], val);
     }

    查询:

     int queryOnTree(int u, int v)
     {
         // 求和
         int res = 0;
         while(top[u] != top[v])
         {
             if(dep[top[u]] < dep[top[v]]) swap(u,v);
             res += Query(1, 1, n, dfn[top[u]], dfn[u]);
             u = faz[top[u]];
         }
         if(dep[u] > dep[v]) swap(u,v);
         res += Query(1, 1, n, dfn[u], dfn[v]);
         return res;
     }

     

  • 相关阅读:
    试算平衡
    对账服务
    会计科目与账户
    支付系统难点全面梳理剖析:核算对账核心
    支付系统设计——你不可不知的会计核心(转发整理)
    支付系统设计之查漏补缺的一环:差错账处理
    支付清算业务总结
    财务对账系统v1.0立项到结项的整体回顾
    DNS视图及压力测试(四)
    一个快速检测系统CPU负载的小程序
  • 原文地址:https://www.cnblogs.com/jaszzz/p/13275568.html
Copyright © 2011-2022 走看看