P8290 填树 题解
题意:
给定一棵树,第 \(i\) 个点的赋值范围是 \([L_i,R_i]\)。计数:选择一条路径,将路径上的点赋值,使得极差 \(\le K\);并求出每种这样赋值方案的权值和。
\(n\le 200\),其余 \(\le 10^9\)。
看见极差,考虑枚举最小值 \(x\),然后统计 \([x,x+k]\) 的答案。
思路很简单,但是下一个问题是:\(x\) 的取值范围高达 \(10^9\),不可能单独枚举具体的值。
一般推到这里发现复杂度和值域有关就可以考虑转战其他思路了。但是这题就是不一样,根本没有其他思路,所以继续推。
这时候我们可以分段处理 \(x\)!就像高斯函数的分段性一样,如果每一段 \(x\) 的答案有相似性,就可以。
当取值范围很大的时候,尝试分段。
怎么分段?要使得每一段 \(x\) 的答案是相似的的,肯定要让每个点的取值范围在这段 \(x\) 中是相似的。那么一个点的取值范围是什么?\([L_i,R_i]\cap [x,x+k]\)。
要让 \([L_i,R_i]\cap [x,x+k]\) 有相似性,想到在 \(L,R,L-k,R-k\) 处分段。
这样,在分出的五段内部,点 \(i\) 的取值范围都是仅和 \(x\) 有关的(而不是和 \(x,L_i\)、\(x+k,R_i\) 的大小关系也有关)或和 \(x\) 无关。
这样分段得到 \(O(n)\) 个段,于是可以计算每个段的答案再求和。
勿忘初心:对于一个段的 \(x\),我们要统计最小权值为 \(x\) 的答案。记 \(S(l,r)\) 为权值在 \([l,r]\) 之间的答案,我们所要求的就是 \(S(x,x+k)-S(x+1,x+k)\)。
考虑 \(S(x,x+k)\) 怎么求。因为 \(S(x+1,x+k)\) 形式类似,只需考虑一个就行。
因为在一个段内,所以我们可以把每个点的取值范围都确定下来,形如 \([ax+b,cx+d]\)(这就是分了段的好处,上面没分段需要带 \(\min/\max\) 才能表示)。
我们发现:每个点的取值可能个数是关于 \(x\) 的一次函数。所以对于这一段的每一个 \(x\),它作为参数给树赋值的方案数都可以看作一个相同的多项式。
如果求出了这个多项式 \(f(x)\),设当前这一段为 \([L,R]\),则这一段的总方案数就是 \(f(L)+f(L+1)+\cdots +f(R)\)。
就算讲过然而到这里又卡住了 …… 果然是数学太菜了吧
因为每个点取值个数都是一次函数,所以 \(f\) 是一个 \(n\) 次多项式。令 \(g(x)=\sum_{i=L}^{x}f(i)\),则 \(g(x)\) 是 \(n+1\) 次多项式。
关于对 \(g(x)\) 是 \(n+1\) 次多项式的证明:CF622F The Sum of the k-th Powers 的参考
(粗略的说,\(g\) 的差分是 \(n\) 次多项式,所以 \(g\) 是 \(n+1\) 次多项式)
既然 \(g\) 是 \(n+1\) 次多项式,而 \(n\) 很小只有 \(200\),我们直接使用拉格朗日插值法,取 \(n+2\) 个点值就能求出 \(g(R)\),即 \(f(L)+\cdots +f(R)\)。
(取 \(l\sim \min(l+n+2,r)\) 的 \(f()\) 值做前缀和即为 \(g\) 在对应处的点值)
好的,我们现在只剩最后一个问题:当 \(x=x_0\) 时,怎么求 \(f(x)\)。
当 \(x\) 确定了,每个点的点权取值范围(进而方案数)也就确定了。
\(dp[x]\) 表示 \(x\) 子树内选一条端点为 \(x\) 的路径并确定路径上点权的方案数。计算 \(dp[x]\) 时采用树上背包合并子树的方式,可以在合并子树时统计所有 LCA 为 \(x\) 的路径贡献的方案数。
方案点权和也可以类似计算。