Count on a Tree II
以前写的用可持久化分块维护。。既难写而且常数还大。。最后在 Luogu 还是开了读优挂才跑过去的。。感觉题解区的 Bitset 维护比我这个不知道高到哪里去了。。
考虑随机在这个树上打 √n 个点作为关键点,然后每个点向上跳找到第一个关键点的期望长度是 √n 的。当然,也有没那么玄学的打点方法,用深度是 √n 倍数并且向下最深深度大于等于根号的点来打,这样打出来点的个数是 √n 的并且明显从每个点向上的长度也是 √n 的。
然后我们先预处理出关键点间两两的答案,做法是从每个关键点跑一次 DFS 。
然后考虑一次询问,对于一次询问我们需要查询这两个点到关键点的路径上有没有什么颜色是不存在于关键点的路径上的。也就是说我们需要维护根到每个节点的某个颜色的数量。直接主席树维护得带 log 不优秀,可以考虑用根号平衡,修改 O(√n) 查询 O(1) ,套个可持久化就好了。
还需要用 ST 表 O(1) 维护 LCA。这样做复杂度就是在线的 O(m√n) 了(虽然常数有点大)。空间是 n√n 的。
代码写的很丑。。
cpp
1 |
|