【题目链接】
【思路要点】
- 可以发现,中心能够存在的位置同样是树上的一个连通块,一个方案合法当且仅当该联通块大小非零。
- 注意到布尔值 “连通块大小非零” 等于 “连通块内部点数” 减去 “连通块内部边数” ,可以考虑枚举存在于最终连通块上的一点或一边,并计算使得该点或边存在于最终连通块上的方案数,再利用上述关系计算答案。
- 以枚举存在于最终连通块上的一点 x x x 为例,我们需要计算出包含 x x x ,且距离 x x x 最远的点距离在 L L L 以内的连通块的个数 f ( x ) f(x) f(x) ,那么最终 x x x 贡献的方案数即为 f ( x ) k f(x)^k f(x)k 。
- 考虑树形 d p dp dp ,记 d p i , x dp_{i,x} dpi,x 表示 i i i 为根的子树中,包含 i i i ,且所有点距离 i i i 不超过 x x x 的连通块个数 + 1 +1 +1 , u p i , x up_{i,x} upi,x 包含 i i i ,不包含 i i i 子树内其余点,且所有点距离 i i i 不超过 x x x 的连通块个数,则有转移
d p i , j = 1 + ∏ x ∈ c h i l d ( i ) d p x , j − 1 dp_{i,j}=1+\prod_{x\in child(i)}dp_{x,j-1} dpi,j=1+x∈child(i)∏dpx,j−1
u p i , j = 1 + u p f a t h e r i , j − 1 ∏ x ∈ c h i l d ( f a t h e r i ) , x ≠ i d p x , j − 2 up_{i,j}=1+up_{father_i,j-1}\prod_{x\in child(father_i),x\ne i}dp_{x,j-2} upi,j=1+upfatheri,j−1x∈child(fatheri),x̸=i∏dpx,j−2- 时间复杂度 O ( N L ) O(NL) O(NL) ,可参考下文 301 301 301 行起的代码。
- 我们最终需要使用的 d p dp dp 值为 d p i , L − 1 , d p i , L , u p i , L dp_{i,L-1},dp_{i,L},up_{i,L} dpi,L−1,dpi,L,upi,L 。
- 计算 d p i dp_i dpi 的过程可以直观地使用长链剖分优化,我们需要额外支持对数组的后缀乘 c c c,和全局 + 1 +1 +1 操作。
- 为全局维护标记 x → a x + b x\rightarrow ax+b x→ax+b ,则全局 + 1 +1 +1 操作可以轻松处理。
- 注意到后缀乘操作时我们一定扫描了剩余的前缀,可以将所扫描的值除去 c c c ,再全局乘以 c c c 。当 c = 0 c=0 c=0 时我们可以视作一次后缀赋值操作,可以再额外维护一个后缀赋值标记来处理。
- 由此,我们可以用长链剖分优化计算 d p i dp_i dpi ,注意到除去 c c c 的过程需要计算逆元,本部分时间复杂度为 O ( N L o g V ) O(NLogV) O(NLogV) 。
- 考虑优化计算 u p i up_i upi ,同样采用长链剖分的思想,我们需要一个转移复杂度为轻边长度和的算法。注意到为了计算 u p i , L up_{i,L} upi,L ,我们只需要计算出 u p i , L − d e p t h i … L up_{i,L-depth_i\dots L} upi,L−depthi…L 即可,其长度同样等于 d e p t h i depth_i depthi 。
- 首先注意到计算 u p i up_i upi 时,我们需要使用 d p i dp_i dpi 的信息,因此需要记录更改前的 d p i dp_i dpi ,实现信息的可回退化,实际操作时直接用 v e c t o r vector vector 记录即可。
- 考虑计算轻边的 u p i up_i upi ,由于需要暴力重构轻边,我们只需要保证复杂度为所有轻边长度和即可,需要一个类似于上文的结构来保证复杂度。
- 计算 p o s pos pos 重儿子 x x x 的 u p x up_x upx 时可以直接扫描轻边的 d p i dp_i d