CC's

Back

树链剖分可以用来维护树上路径的信息。把树上的节点拆成不超过O(logn)O(\log n)段连续的路径(链),以映射到线段树或者什么的构来维护数据。

依照子树的大小,将最大子树作为重边,其他子树作为轻边,从而在树上拆分出多条链。为同一条链上的节点连续编号,完成剖分。至于剩下的,依照编号一条链可以连续的映射到数据结构的某个取间内,用类似于倍增LCA的方法在树上得到每一个询问所覆盖的链的起始与结尾然后继续其他操作就可以了。

通常策略#

  • 对于子树的大小统计,dfs即可。
  • 之后节点编号使用先序的dfs序,并且优先进入重边,以保证链上节点的编号连续。
  • 为了在链上快速跳转,还需要记录每个节点所在链的头。

具体的代码可以看下面两个题目。其实我也是从别处抄了板子

HDU 3966 Aragorn’s Story#

题目要求区间修改某条路径上所有节点的权值,查询某个点的权值。

就剖,剖完线段树还是树状数组区间修改单点查询。

CF343D Water Tree#

稍微有点不一样。修改1要求为点的整个子树打标记,修改2要求取消节点到根节点上的标记。

按照dfs序的编号方式,为每一个节点记录进入时间和离开时间,就能得到该节点子树映射后的连续区间。那么浇水就可以套一个线段树直接改了。清空水往根节点跳然后修改一路上经过的链。

树链剖分
https://astro-pure.js.org/blog/heavy-light-decomposition
Author Cheng Chen
Published at 2020年2月18日
Comment seems to stuck. Try to refresh?✨