Loading

P8990 题解

简要题面

给定大小为 $n$ 有根树(根为 $1$)和一个不包括根的操作序列,每次按照操作序列染色。当一个时刻所有被染色的点的子树中所有点也被染色了,将答案加上此时所有被染色的点的形成连通块数量。输出操作结束之后的答案。

还会有 $m$ 删边和加边的操作。每次删除后再次询问答案。

$n,m\le 10^5$。

Sol

先考虑转化“所有被染色的点的子树都被染色”这个条件,因为每次单独考虑一个节点的子树是不好处理的(尤其是在修改的时候父子关系可能改变的情况下)。会发现这个条件等价于所有没有被染色的点会恰好处于一个连通块中,且连通块的根节点为 $1$。原图是一棵树,因此连通块也应该为树,即应该满足 $N=M+1$ 的条件。其中 $N$ 为节点数,$M$ 为边数。

此时我们有了能够比较快速判断一个状态是否会给答案有贡献的方法,更具体的,假如到了第 $i$ 次操作之后,我们只需要考虑此时是否满足 $N-i=P+1$ 的条件。其中 $P$ 为没有被染色点之间边的数量。

对于 $P$ 进行维护,会发现一条边 $(u,v)$ 连接的两个节点在其中一个点被选择之前对 $P$ 的贡献始终为 $1$ 之后一直是 $0$,即是一个区间贡献的形式。这样转化的好处有二,其一,我们不需要在意 $(u,v)$ 的具体的祖先关系,这样在后面更改操作能够容易维护;其二,这样的形式可以通过对于每个时间点建立线段树后 $O(\log n)$ 维护。

此时我们成功一半了,但是还需要考虑如何计算答案。在一个符合条件的情况下,我们按照同样的套路观察边的情况。不难发现此时被染色点形成连通块的数量应该为:所有一边的点被染色另一边的点不被染色边的数量,设其为 $Q$。

再次观察 $(u,v)$,在其中一个点被染色之后,且另一个点没有被染色的时候对于 $Q$ 的贡献为 $1$。其他的时候一直为 $0$。这和 $P$ 的更改情况几乎一样,我们同样可以在线段树上维护。这样同样可以在 $\log n$ 的时间内维护,至此整道题的思路梳理完。

具体实现上,在线段树上维护两个个参数,分别表示 $N-i-P$,$Q$。其中 $N-i-P$ 为区间每个点 $N-i-P$ 的最大值,询问的时候如果 $N-i-P=1$ 则贡献为 $Q$。

但是直接这样暴力判断在查询的时候会导致往下推的次数太多,因此可以再记录一个参数,表示区间 $N-i-P$ 的最小值,如果最小值 $> 1$,则在查询的时候可以直接跳过。

每次加入一条边(以下假设 $u$ 在序列中出现的时间早于 $v$),将 $[1,t_u)$ 的 $N-i-P$ 减 $1$,将 $[t_u,t_v)$ 的 $Q$ 加一。删除同理。

复杂度 $O(m\log n)$。

代码实现

LOJ 记录

posted @ 2023-07-18 15:16  Jryno1  阅读(19)  评论(0)    收藏  举报  来源