以前做过两道LCA单调性的题,但是不知道这玩意也叫做虚树哪个混蛋起的第二个名搞的我还以为是是什么高级数据结构呢,弄得我出去听课都听不懂
题意
给定一棵$n$个点的树,有$q$组询问,每一组给定了一些节点,问这些节点每个节点管辖多少个点
定义某个点被管辖当它到这个给定的点距离最小(距离相等取标号最小)
n<=300000, q<=300000,m[1]+m[2]+…+m[q]<=300000
m[i]为给定节点的标号
分析
手算一下我们发现节点个数约为$x=\sqrt{2n}$个,极限不到800个点.
显然我们不能在每一次询问做$O(n)$的dp,会T掉.
如果我们能够每一次询问时做$O(x)$的dp,问题就可以解决.
我们还是根据LCA单调性建出虚树,然后对虚树处理.
因为我们要做关于这棵虚树中的点的处理,那么需要预先求得每个节点子树大小.
将虚树中的节点按照dfs序排序,我们就可以两次循环处理出每一条虚树中的每个端点由哪一个节点来控制.
此时我们需要处理每一条边夹在两个端点间的那些节点的控制权
如果一条边的两个端点都由同一个节点来控制,显然中间这些节点都应该被相同的节点控制;
如果两端点由不同节点控制,则需要找到这两个控制点的路径中点在哪里,在中点两侧的节点由两个控制点分别控制.
第二种情况再仔细处理一下路径长度的奇偶性和标号大小即可.
代码
1 | #include <cstdio> |