「ZJOI2019」Minimax 搜索

第一次写动态dp居然是这种毒瘤题

直接求稳定度为(x)感觉不好求

我们差分一下转为求稳定度小于等于(x)的所有方案减去稳定度小于等于(x-1)的所有方案

注意到叶子结点的权值都是不相同的

我们考虑贡献答案的叶子结点到根的那条链

考虑根节点的权值(w)改变实际上就是链上有点的权值改变了

所以我们考虑容斥

对于当前的稳定值为大于等于(v)

用总的方案数减去不会改变答案的方案数

那么后者就是

断开链上的边以后

那条链上的每个点考虑它的子树中使得在当前稳定值下满足不会改变这个点权值的方案数

我们分链上点深度的奇偶性讨论

这里以奇数深度节点为例

那么它的儿子的值都要小于等于(w)

于是设(f[x])表示以(x)点的值小于等于(w)的方案数

那么我们考虑转移方程

如果(x)是叶子

那么(f[x]=(x<=w)+(x+v<=w))

如果(x)的深度是奇数

那么他的所有儿子都要满足条件

所以

(f[x]=prod _{v in son[x]} f[v])

如果(x)的深度是偶数

那么他只需要有一个儿子满足条件即可

(cnt[x])为x子树中的全部方案数

容斥一下有

(f[x]=cnt[x]-prod _{v in son[x]}(cnt[v]-f[v]))

这个式子不好看

我们定义新的(g[x])

(x)的深度为偶数时

(g[x]=f[x])

(x)的深度为奇数时

(g[x]=cnt[x]-f[x])

我们发现我们有了统一的转移

(g[x]=cnt[x]-prod_{v in son[x]}g[v])

那么该链上节点方案数就是他所有儿子的方案数之积

对于链上节点深度为偶数的方案数就是全部反过来

我们发现每一次稳定值的改变就是改变一些叶子的(f)

这好像就是动态dp!

利用上面的统一转移我们可以很方便的搞动态dp

时间复杂度是(O(nlog^2n))

一些优化

把每个链上的节点看做一棵树的根把原树拆成几棵树可以加速树剖

这里动态dp不需要矩阵,可以用一个一次函数方便地搞定

一点疑惑

感觉这里动态dp是要记一下每个点dp值为0的个数的

不然会被卡

但是我没记好像也没事?

code

原文地址:https://www.cnblogs.com/deaf/p/13227004.html