$\Large\mathscr{D}\mathcal{escription}$
给定一颗 $n$ 节点的树,每个节点都有一种颜色。求每个子树中出现次数最多的颜色的编号和。
$\Large\mathscr{S}\mathcal{olution}$
这里介绍两种方法。
法一 $:$ $Dsu$ $on$ $Tree$
$\qquad$ 先放一下大佬的博客 $:$ $Dsu$ $on$ $Tree$ 入门
$\qquad$ 模板题。
$\qquad$ 直接走流程 $:$
- 先剖出轻重链。
- $Dfs$ 遍历节点。
- 先递归所有轻儿子,同时消除影响。
- 再递归重儿子,不消除影响。
- 统计所有轻儿子的贡献。并更新该节点答案。
- 删去所有轻儿子的贡献。
$\qquad$ 复杂度 $:$ $\mathcal{O}(n log_n)$
$\qquad$ 简单证明 $:$ 每个点到根的路径上轻边个数不会超过 $log_n$ 条。所以每个点被作为轻边访问到的次数不会超过 $log_n$ 次。所以复杂度是 $\mathcal{O}(n log_n)$。
1 | // Dsu on Tree |
法二 $:$ 线段树合并
$\qquad$ 对于每个节点开一颗动态开点的权值线段树。维护单种颜色出现最多的次数和出现次数最多的颜色的编号和。
$\qquad$ 然后 $Dfs$ 就行了。递归到点 $u$ 时,把他的每一个儿子 $v$ 的线段树与自己合并起来。直接更新答案。
$\qquad$ 复杂度 $:$ $\mathcal{O}(n log_n)$
$\qquad$ 较 $Dsu$ $on$ $Tree$ 的缺点 $:$ 空间要开 $nlog_n$
1 | // 线段树合并 |