此题和前面两个dfs序列其实是差不多的。只是稍微复杂点。
首先需要明白:某个点的子树就是DFS序列里一段连续的区间。所以我们要给其子树赋值,就是给对应的dfs序列中的连续区间赋值。
那么首先用dfs预处理出连续区间。然后离线的保存所有的询问。然后按dfs序列来搜,每搜到一个节点,则更新其区间,然后统计出来有多少个就可以了,这和前面的那两题是差不多的。这个步骤可以用线段树来维护,或者树状数组来维护。然后退出的时候要保证不影响其他的点,那么退出的时候-1操作来复原就好了,类似于usaco那题。
以下这一段来自:http://hi.baidu.com/lydrainbowcat/item/7daee04e7df29e94823ae1c7
然后:统计答案的时候,DFS一遍,对于一个点x,以下操作会对其造成影响:
(0)只要有涉及x的操作,以x为根的子树中所有节点必定和x有公共部分。
(1)形如(x,y)的操作。这样显然以y为根的子树中所有节点都与x有公共部分。
(2)形如(fa,z)的操作,其中fa是x的祖先。以z为根的子树中所有节点也与x有公共部分。
因此DFS进入点x时,把x为根的子树、以及从x出发的所有操作对应的y为根的子树的DFS序列区间都+1,退出时都-1。
线段树中,如果一个区间被+过,那这整个区间就与x有公共部分,否则应该用左右孩子的公共部分来更新它。每次直接ASK线段树根节点即可。