树上数子树颜色
First Post:
Last Update:
Word Count:
Read Time:
Page View: loading...
Last Update:
Word Count:
572
Read Time:
1 min
Page View: loading...
问题:
有一类树上问题形式如下:
给定一棵树,大小为
,点有颜色,分别记为 。对于树上的每个子树,求子树中不同颜色数量。
常见的做法有树上启发式合并和莫队算法。
dsu on tree
树上启发式合并一般可以用数组实现或者使用 set
。
数组
使用计数数组维护颜色出现的数量,由于不能在每个节点上都开一个数组,因此需要将所有数据都记到这个数组上。
对于这道题,算法流程是:
- 计算每个子树的大小,并且称
- 重子节点表示其子节点中子树最大的子结点,若有多个子树最大的子结点,任取其一;若无子节点,则亦无重子节点;
- 轻子节点表示剩余的子结点;
- 重边为节点到其重子节点上的边;
- 轻边为重边以外的边;
- 在树上进行 DFS(
函数),对于每个节点: - 将
应用到所有轻子节点上,然后撤销其对计数数组的影响; - 将
应用到重子节点上; - 恢复轻子节点的子树对计数数组的影响。
- 将
对于一个节点,可能会多次访问,并且容易发现节点被访问的次数等于节点到根节点路径上轻边数量。
又因为任意位置到根节点路径上轻边数量为
set
相比使用数组维护,set
维护的复杂度会多一个
直接对树应用 DFS,返回子树的颜色集合(返回时移动构造做到 set
往大的 set
上合并;类似上文的分析技巧,可以证明一个颜色至多被合并
由于不需要考虑撤销对计数数组的影响,这种方法在大多数时候更好实现。
Mo-algo
将树拍成 dfs 序,容易处理出每个子树在 dfs 序上的范围,使用莫队算法数区间颜色数。
由于只有