P6773 [NOI2020] 命运

首先显然是个 dp。

然后我们来考虑设计状态。一个比较自然的想法是设 \(f_u,g_u\) 分别表示 \(u\) 子树内满足 牵扯到其子树 / 完全在其子树内 的限制的答案。但是 \(g_u\)\(v\) 合并来时,倘若不选 \((u,v)\) 这条边,按理说应该是 \(f_v\) ,但这时多考虑了一些限制,无法转移。

再考虑一个自然的想法,我们想知道对于当前这个子树 \(u\) 的若干个限制里面,哪些已经满足了,哪些是我们仍要满足的。这个你或许可以尝试给限制重编号来做,但我们有更好的做法。考虑记录 \(rt \to u\) 的路径上, \(u\) 上一次选的边是哪一条(不包括自己和父亲的那条边),这个可以用这条边的深度来代替。

那么我们令 \(dp_{u,j}\) 表示 \(u\) 上一次选的边深度为 \(j\),要考虑所有牵扯到 \(u\) 且深度 \(\leq j\) 的限制,子树 \(u\) 内的方案数。

我们定义 \(type(u,j)=0/1/2\),分别表示 \(u\) 上一次选 \(j\) 之后,\((fa,u)\) 这一条边 没有方案/必须选/选不选都行,这个东西是随着 \(j\) 的减小由 \(2\to1\to0\) 的,我们可以 \(O(1)\) 求出分界点。

\[dp_{u,j}=\begin{cases}0,type(u,j)=0\\\Pi_{son}dp_{son,dep[u]},type(u,j)=1\\\Pi_{son}dp_{son,dep[u]}+\Pi_{son}dp_{son,j},type(u,j)=2\\\end{cases} \]

现在我们已经会了 \(O(n^2)\),考虑怎么优化到 \(O(n\log n)\)

观察转移方程,它分为三部分,第一部分可以覆盖,第二部分可以同一位置相乘,第三部分可以同一位置相乘之后再区间加。套路地考虑整体 DP,用带区间覆盖、区间乘、区间加标记的线段树合并维护这一 DP 过程即可。

posted @ 2023-02-21 16:53  PYD1  阅读(24)  评论(1编辑  收藏  举报