[学习笔记]Dsu On Tree

[dsu on tree]【学习笔记】 - Candy? - 博客园

题单:

 

 

也称:树上启发式合并

可以解决绝大部分不带修改的离线询问的子树查询问题

 

流程:

1.重链剖分找重儿子

2.sol:全局用桶或者数据结构存信息。
  ①递归所有的轻儿子,回溯前删除贡献

  ②递归重儿子,不删除贡献

  ③暴力找所有轻儿子,加入贡献

  ④更新x的答案

  ⑤如果x是父亲的轻儿子,再把整个子树贡献删除(信息只有子树的,有时可以不用再dfs去重,可以直接清空)

正确性:

一个点的轻儿子会暴力更新到所有信息,重儿子链不会删除贡献,所以重儿子子树经过④之后轻儿子的贡献会保留下来,重儿子子树都有。

数据结构只会保留x子树的。

复杂度:

主要是④的暴力和⑤的删除。一个点到根的路径一共只有logn条轻边

每个轻边会额外删除一次、插入一次。总共是:O(nlogn)的

 

利用重链剖分的性质,保留重儿子的信息,轻儿子暴力更新

O(n^2)->O(nlogn)

 

好处:

(其实许多dsu的题都可以用主席树,线段树合并处理。)

1.好写

2.空间小。O(n)。全局的桶使得不用再花费logn的空间

3.可以精确打击。枚举轻儿子是把所有点再找一遍直接贡献到x上去。线段树合并和主席树就不太能精确查找。好比莫队。

4.可以处理一些有根树点分治

 

例题:

为了重儿子的信息一直适用,都是记录的绝对大小,也就是深度。

单纯和深度相关,并且边权为1的话,也可以考虑长链剖分

CF570D Tree Requests 

(这个题,可以用桶前后差分做到O(n),长链剖分也可以O(n)的)

二进制数记录某个深度的所有字符出现次数奇偶性

CF208E Blood Cousins 

倍增找到k级祖先,记录某个深度的点出现次数

CF246E Blood Cousins Return 

每个深度用set去重。

CF741D Arpa’s letter-marked tree and Mehrdad’s Dokhtar-kosh paths

有根树点分治:

CF741D Arpa’s letter-marked tree and Mehrdad’s Dokhtar-kosh paths

 

挺不错的算法

有点类似分块莫队三元环计数。用顺序和规模限制了复杂度。且这个还是一个logn

 

转载于:https://www.cnblogs.com/Miracevin/p/10505423.html

你可能感兴趣的:(数据结构与算法)