• 树链剖分与线段树


    一 说明

    在树中进行点更新、区间更新、区间查询等操作,可以使用线段树来维护和处理。

    二 图解

    一棵树如下图所示。

    树链剖分之后的节点序列和下标序列如下图所示。

    节点序列对应的权值如下图所示。

    根据 w[] 序列创建线段树,如下图所示。

    查询节点 u 到 v 路径上节点权值的最值与和值的方法如下。

    • 若 u 和 v 在同一条重链上,则在线段树上查询其对应的下标区间 [id[u ],id[v ]]即可。

    • 若 u 和 v 不在同一条重链上,则一边查询,一边将 u 和 v 向同一条重链上移。对于顶端节点深度大的节点,先查询其到顶端节点的区间,然后一边上移一边查询,直到上移到同一条重链上,再查询在同一条重链上的区间。

    查询节点 6~9 权值的最值与和值(包括6和9节点),过程如下。

    1 读取 top[6]=1,top[9]=2,两者不相等则说明其不在一条重链上,且 top[9]的深度大,先查询 top[9]~9之间的最值与和值。

    首先得到节点 2 和 9 对应的节点序列下标 7 和 9。

    然后在线段树中查询 [7, 9] 区间的最值与和值。[7,9] 区间的最值与和值:Max=15,Sum=22。

    2 将 u 上移到 top[9](2号节点)的父节点,即 1 号节点,此时 1 和 6 在同一条链上。

    节点 1 和 6 对应的线段树下标为 1 和 3。

    在线段树中查询到 [1, 3] 区间的最值与和值分别为 20、31,如下图所示 。 再与前面的结果求最大值与和值 , 则 Max=max(Max,20)=max(15, 20)=20,Sum=Sum+31=22+31=53。

    区间更新的方法与此类似,若不在一条链上,则一边更新,一边向同一条链上靠,最后在同一条链上更新即可。

    注意:更新和查询时均需要先得到节点对应的线段树下标,再在线段树上更新和查询。

  • 相关阅读:
    【QT开发(11)】QT 线程QThread
    HTTP/3,它来了
    Go 语言面试题(三):并发编程
    docker搭建redis哨兵集群和分片集群
    基于java的运动健康微信小程序
    if-else练习
    【MySQL】索引
    Android Studio实现内容丰富的安卓博客发布平台
    Linux磁盘分配 把home的空间扩容给root
    Python实战:使用requests通过post方式提交json数据
  • 原文地址:https://blog.csdn.net/chengqiuming/article/details/127658294