注意到 w(S) 的定义含一个 max,于是考虑统计 w(S)≤R 的个数并差分。
首先如果 W∈S 显然有 w(S)=1,故下文不考虑此情况。
显然,如果要改变 W,一定是改为 W±1,并且小于 W 的一定改为 W+1,大于 W 的一定改为 W−1。
考虑分别求出把某些权值小于 W 的叶子改为 W+1 能影响到根或把某些权值大于 W 的叶子改为 W−1 能影响到根的方案数,取补集再容斥一下就可以得到答案。
考虑小于 W 的。
出于方便起见,考虑对概率进行 DP,而不是方案数(是指在当前 R 限制下有贡献的叶子以 12 的概率出现时的总概率)。
设 fu 表示使 u 的权值大于 W 的概率。
易得 fu={1−∏v∈son(u)(1−fv),depth(u)≡1(mod2)∏v∈son(u)fv,depth(u)≡0(mod2)
这样做起来很麻烦,考虑设 Fu={1−fu,depth(u)≡1(mod2)fu,depth(u)≡0(mod2),则转移变成 Fu=∏v∈son(u)(1−Fv)
大于的类似。
设 gu 表示使 u 的权值小于 W 的概率。
易得 gu={∏v∈son(u)gv,depth(u)≡1(mod2)1−∏v∈son(u)(1−gv),depth(u)≡0(mod2)
类似地设 Gu={gu,depth(u)≡1(mod2)1−gu,depth(u)≡0(mod2) 即可。
发现每次改变 R 只会改变一个叶子的贡献,动态 DP 即可。
由于我比较傻,所以我在这里再写一下动态 DP 的细节(
对于小于 W 的,设 Fu 表示总 DP 值,F′u 表示对轻儿子的 DP 值。
那么转移可以写作 Fu=(1−Fsonu)F′u=−F′u⋅Fsonu+F′u
容易发现这是一个一次函数的形式,考虑用线段树维护区间的一次函数复合即可。
调了半年发现我原来还会出数组越界的锅……
代码:
1 |
|