【cf741】D. Arpa’s letter-marked tree and Mehrdad’s Dokhtar-kosh paths(dsu on tree)
传送门 题意: 给出一颗以 \(1\) 为根的有根树,树边带有一个字符( \(a\) ~ \(v\) )的信息。 输出对于每个结点,其子树内最长的简单路径并且满足边上的字符能够组成回文串。 思路: 显然最终的答案分为两部分,子树内部的答案,经过当前根结点的答案。 第一种答案很好处理。类似于点分治,主要处理第二种答案。 树上路径可以考虑找到 \(lca\) ,维护点到根节点的信息。 题目中的回文串可以等价于,出现奇数次的字符不超过 \(1\) 个。我们将字符状压一下,那么维护点到根的信息就很方便了;同理求出两点间的信息也很方便。 因为要枚举两条链中的结点,我们可以类似于树 \(dp\) 那样,保留之前的信息,然后枚举这条链更新答案并且更新信息。 这里显然枚举时枚举轻边最优(类似于启发式合并),那么可以采用 \(dsu\ on\ tree\) ,算法会保留重儿子的信息,我们直接暴力轻儿子即可。 根据 \(dsu\ on\ tree\) 算法的思想,每个结点只会被暴力到 \(O(logn)\) 次,所以算法的时间复杂度为 \(O(nlogn)\) 。 感觉挺考察对 \(dsu\ on\ tree\) 的理解的。。细节见代码吧: /* * Author: heyuhhh * Created Time: 2019/11/15 16:10:20 */ #include <bits/stdc++