CF1749F Distance to the Path

· · 题解

这道题太 OI 啦!

观察发现 d 很小,我们要利用这一点。

1 为根,维护 f_{d, i} 表示 i 子树内距离 id 的所有节点被加上的值,则查询 v 时,对 vk 级祖先 u\sum f_{k, u}

A(u, d) 表示 u 子树内距离 u 不大于 d 的点集。

考虑一次修改 (u, v, k, d),设 x = \operatorname{lca}(u, v)。则 A(u, d) 会受到贡献,但 A(fa_u, d) 同样会受到贡献,这样 A(u, d - 1) 就会受到重复贡献。因此,对于 u,我们让 A(u, d) \backslash A(u, d - 1) 受到贡献,相当于令 f_{d, u} 加上 k

我们对 u, v 路径上所有节点都执行这样的操作后,发现还有 A(x, d - 1)x 子树外距离 x 不大于 d 的节点没有受到贡献。这部分是平凡的,容易转化为 \mathcal{O}(d) 次对 f 的单点加。

接下来考虑实现。查询为 \mathcal{O}(d)f 的单点查,修改为 \mathcal{O}(1)f_d 的链加和 \mathcal{O}(d)f 的单点加。链加单点查拆成两条竖直链,每条直链再差分变成两条到根的链,据此转化为子树加单点求和,用树状数组维护。单点加对单点查的贡献容易统计。

综上,时间复杂度 \mathcal{O}((n + qd)\log n)。代码。