HDU 5574 Colorful Tree
• 给出一棵树,每个点有初始的颜色,支持两种操作
• 将一个点的子树染成一种给定颜色
• 问一个点的子树里有几种不同的颜色
• 𝑛, 𝑚 ≤ 10^6
本题可以做到一个logn
考虑每个颜色的虚树
把每个点的权值+1,dfs序相邻的LCA权值-1
那么,对于每个点的子树,假设有m个点,那么有m-1个LCA,并且这些LCA一定在这个子树里,权值和的贡献恰好是1
找出dfs序,考虑用dfs序维护val,直接子树查询
考虑在修改的时候维护
dfs序上大概是这样的
用黑色覆盖完之后,dfs序相邻的LCA会-1
内部:
发现,对于之前形成连续dfs序部分的点,内部相邻的点的LCA已经减过1了。
只要把两段合并 ,并且把两个端点LCA减掉1
外部:
画灰色线部分,本来有LCA的贡献,现在没有了,这些都要在对应位置减去
如果其他地方还有黑色的部分,也要把两段LCA计算上
就是一些连续段的操作
每个颜色开一个set,维护自己的连续段
全局再开一个set,维护全局的连续段
val的维护用树状数组就可以了
总结:
漂亮之处就是每个颜色的内部“差分”处理,使得颜色之间贡献独立(很多种类计数,不是暴力的,都可以考虑这个套路)
而且不光是颜色之间独立,每个点贡献也是独立的!
使得很好维护
dfs序列上,内部已经分成连续段的权值已经不用修改
只用修改后继前驱的LCA即可。