CF741D - Arpa's letter-marked tree and Mehrdad's Dokhtar-kosh paths 题解

orz 一个 2900 D1D,不过还是被我自己想出来了(

这种关于统计所有树上路径的,应该套路地使用淀粉质。不过我只会 dsu on tree/kk,而且 yy 出来的是 \(\mathrm O(22n\log n)\) 的垃圾复杂度,没想到竟然和官方题解重合?

显然一个子树内的路径,要么穿过根,要么就一定包含在一个子子树里面。于是我们可以对每个子树先算出那些穿过根的最长的符合要求的路径,最终 dfs 与儿子合并一下即可。

很自然的想到,可以预处理出每个节点处的关于每个字符出现次数奇偶性的前缀 bitmask,然后一条路径的 bitmask 显然是 \(Msk_x\oplus Msk_y\)。我们要统计的就是那些 \(x,y\) 属于不同子子树的满足 \(|Msk_x\oplus Msk_y|\leq 1\) 的路径 \(x\to y\),它的长度为 \(dep_x+dep_y-2dep_{a}\),其中 \(a\) 是当前根。这个 \(-2dep_a\) 是定值,我们只需要最大化 \(dep_x+dep_y\)

不难想到这样一个暴力:对于每个 \(a\),用关于子树大小的复杂度处理:实时维护一个 \(mx\) 数组,\(mx_{msk}\) 表示 \(Msk_x=msk\) 的最大 \(dep_x\)。然后依次考虑每个子树,先用这个子树中每个节点贡献最大深度和,然后松弛这个 \(mx\)(这样能让「属于不同子子树」获得保证)。贡献的具体方式是:枚举 \(Msk_x\oplus Msk_y\)(显然是 \(\mathrm O(22)\) 的),然后显然可以确定出 \(Msk_y\),往 \(mx\) 里调用一下即可。

考虑把这个暴力用 dsu on tree 进行优化。显然是可行的,而且不是那么套路的 dsu on tree,实现方式有点小变化。值得一提的是:\(mx\) 这东西虽然不可撤销,但 dsu on tree 本来就不用撤销,而只需要全局清空;于是只需要赋为 \(-\infty\) 而不需要换成 set 等数据结构。

code

posted @ 2021-01-23 17:10  ycx060617  阅读(59)  评论(0编辑  收藏  举报