树链剖分详解

38 篇文章 0 订阅
13 篇文章 5 订阅

简介

  • 树链剖分,一种对树进行划分的算法,它先通过轻重边剖分将树分为多条链。

  • 保证每个点属于且只属于一条链,然后再通过数据结构(树状数组、SBT、SPLAY、线段树等)来维护每一条链。

  • 它能巧妙地将树上信息映射到线性结构上(如套用线段树),应用广泛。

  • 接下来,我们通过一个问题来探究树链剖分算法。

详解

【问题】

  • 在一棵树上进行路径的修改、求极值、求和

【探究】

  • 暴力计算固然可行,但当树退化成链时,查询操作就变成了 O(N) 了,显然超时。

  • 发现操作与线段树类似,可是区间处理又成了问题。

【引入】

  • 树链,就是树上的 路径

  • 剖分,就是把路径分类为 重链轻链

  • 树链剖分就是把一些点合成一条路径,使其在线段树中的编号(下标)有序,并用线段树来维护。

  • 这样就可以使得查询、修改的效率大大提高。

  • 假设我们把路径分好链了 (先不要在乎是怎么分的),每次询问两个点对 xy 时,

  • x y 在同一链中,直接 询问线段树中的 u v因为同一条链中下标是连续的

  • 其中 u v x y 对应的线段树中的点。

  • 若不在同一链中,我们从深度大的点上一点一点向上爬,

  • 每次记录该点所在的链上的情况,直到 x y 在同一条链上即可。

  • 注意树链剖分中的线段树中每个 点 代表的意义可以是原图的 边 或 点 。

【设置数组】

  • size[v] 表示以 v 为根的子树的节点数,

  • dep[v] 表示 v 的深度(根深度为1),

  • top[v] 表示 v 所在的链的顶端节点,

  • fa[v] 表示 v 的父亲,

  • son[v] 表示与 v 在同一重链上的 v 的儿子节点(姑且称为 重儿子 ),

  • tree[v] 表示节点 v 在线段树中的编号,

  • pre[v] 表示线段树中编号是 v 的节点所对应的原图中的点(与 tree 相反,互为反函数)

  • 只需把以上信息求出,即可 O(logN) 处理操作!

【术语解释】

  • 重儿子 size[u] v 的子节点中 size最大的,那么 u 就是 v重儿子

  • 轻儿子 v 的其它子节点。

  • 重边 :点 v 与其重儿子的连边。

  • 轻边 :点 v 与其轻儿子的连边。

  • 重链 :由 重边 连成的路径。

  • 轻链 : 即 轻边

【性质】

剖分后的树有如下 性质 (易证):

  1. 性质①: 如果 (v,u) 为轻边,则 size[u]2<size[v]

  2. 性质②: 从根到某一点的路径上轻链重链的个数都不大于 logN

  3. 【预处理算法实现】

    • 我们可以用两个 dfs 来求出 fadeepsizesontoptreepre
      dfs1 : 把 fadeepsizeson 求出来,比较简单。
      dfs2 :

      1. 我们依次标记 tree[v] (按 dfs 序),同时得到 pre

      2. 对于 v ,当 son[v] 存在(即 v 不是叶子节点)时,显然有

        top[son[v]]=top[v]
        。(没有就直接退出

      3. 然后我们先搜索 v 重儿子 u ,并把 u 重儿子重孙子……的 top 值也置为 top[v]

      4. 接着我们再搜索 v 轻儿子 u,并把 u 重儿子重孙子……的 top 值置为 u

    • 将树中各边的权值在线段树中更新,建链和建线段树的过程就完成了!

    【查询&修改算法实现】

    • 假设将 u v 的路径上每条边的权值都加上x。

    • f1=top[u]f2=top[v]

    • f1<>f2 时,不妨设 dep[f1]dep[f2] ,那么就更新 u f1 的权值(时间复杂度为 O(logn) ),并使 u=fa[f1]

    • f1=f2 时, u v 在同一条重链上,直接更新 u v 路径上的点的权值(时间复杂度为 O(logn) ),修改完成;

    • 重复上述过程,直到修改完成!

【模板题&附加代码】

总结

  • 树链剖分算法可以有效而简便地处理树上问题,使算法优化很多!
  • 13
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值