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即可。

 

posted @ 2019-02-15 18:01  *Miracle*  阅读(493)  评论(0编辑  收藏  举报