题解 LGP4365 【[九省联考2018]秘密袭击coat】

题解 LGP4365 【[九省联考2018]秘密袭击coat】

前置知识

线段树合并,拉格朗日插值

大概后文重点分析了线段树合并的复杂度

\(\texttt{Solution}\)

一脸 dp 的样子,我们来推一推式子

枚举 \(S\) 为一个点数不小于 \(k\) 的树上连通块

\(val(S,k)\) 为集合 \(S\) 中的第 \(k\) 大权值

\(cnt(S,v)\) 为集合 \(S\) 中不小于 \(v\) 的元素个数

\[\sum_{S}val(S,k)=\sum_S\sum_{v=1}^w[cnt(S,v)\geq k] \]

此时我们可以丢掉 \(S\) 中点数的限制,交换求和符号

\[ANS=\sum_{v=1}^w\sum_{S}[cnt(S,v)\geq k] \]

即我们需要对于每个 \(v\) 求出有多少个树上连通块里权值不小于 \(v\) 的点个数不小于 \(k\)

设计一个暴力的 dp 状态:

\(f_{x,i,j}\) 表示以点 \(x\) 为根的连通块中权值不小于 \(i\) 的点有 \(j\) 个的连通块数

转移显然是树上背包

最后的答案应该是 \(\sum_{i}\sum_{x}\sum_{j=k}^nf_{x,i,j}\)

暴力的复杂度很高,我们考虑优化

广为人知的是,树上背包问题是一个卷积,我们用生成函数的角度思考

\(F_{x,i}(z)=\sum_{j=0}^nf_{x,i,j}x^j\)

那么 \(F_{x,i}=z^{[d_x\geq i]}\prod_{y}(F_{y,i}+1)\)

由于我们最后要求 \(\sum_i\sum_x\sum_{j=k}^n[z^j]F_{x,i}\)

我们设 \(G_{x,i}=\sum_{y\in sub(x)}F_{x,i}\)

转移显然是 \(G_{x,i}=F_{x,i}+\sum_{y\in son(x)}G{y,i}\)

答案简化为 \(\sum_i\sum_{j=k}^n[z^j]G_{1,i}\)

由于转移中与 \(i\) 的关联极小,我们希望对于所有 \(i\in[1,w]\) 做整体 dp

由于多项式乘法复杂度较高,我们考虑带入点值计算多项式,最后再插值回来

我们现在只需对于点值 \([0,n]\) 都算一遍整体 dp 即可

考虑建立以 \(i\) 为下标的线段树,所有的转移都能用矩阵表示,即:

\([f,g,1]\times \left[\begin{matrix}a&c&0\\0&1&0\\b&d& 1\end{matrix}\right]\)

考虑矩阵能简化为四元组运算的形式,即大多数题解中提到的“变换”

容易讨论,不展开叙述

本题的线段树合并与一般线段树合并不同的地方在于其区间的修改

例如线段树的初值:

\(F_{x,i}=z^{[i\leq d_x]}\),其中 \(z\) 是枚举的点值,为常数

我们应该将 \([1,d_x]\) 赋值为 \(z\)\([d_x+1,w]\) 赋值为 \(1\)

为了让复杂度正确,我们显然不能让点数达到 \(O(nw)\)

我们直接利用懒标记,显然初始节点个数确为 \(O(n\log w)\)

对于线段树合并操作,我们知道我们得保证遍历一个点后“删除”一个点复杂度才正确

我们考虑合并时直接在存在一棵线段树节点没有儿子时返回即可

由于有一棵树往下已经没有儿子,那么实际上这段区间的矩阵懒标记均相同,容易处理

对于 merge 里 pushdown ,一定是两个线段树节点此时均有儿子时才会去做,事实上此时两节点一定会有左右儿子,所以并不增加节点个数

总复杂度为 \(O(n^2\log w)\)

众所周知区间修改的 \(\log\) 常数不小,线段树里还有矩阵乘法,属于是跑不过暴力(

code

posted @ 2021-09-07 22:38  juju527  阅读(33)  评论(0编辑  收藏  举报