题意简述
一棵树,边有 $1$ 或 $2$ 的边权,多次询问从点 $u$ 到 $v$,每次移动最多能走 $w$(不能在两点之间停下),要几次才能到达。
$n, m\le 10^5$。
主要思路
这个题感觉有一车 $O(n\sqrt{n})$ 做法?这里介绍一种在线的树分块做法。
设 $M = \sqrt{n}$。
先钦定根,定义点 $u$ 的深度 $dep(u)$ 为到根路径上的边数。
那么我们将 $M | dep(u)$ 的节点设为关键点,于是这棵树就被分为若干块(关键点属于其下面的块)。(若一块大小不足 $M$ 跟上面的块合并。)
这样每个块的大小就不小于 $M$,个数就不大于 $M$,且直径最大为 $2M$(此处直径指连通块中两点路径间最多的边的数量)。
显然对于询问 $(u, v, w)$,从两个人两边出发直到碰头所用的总步数和单人走完是相同的。
那么若 $u, v$ 在同一块中,则直接暴力每次将较深的一个往上跳一条边就行了。
若在不同块中,则由于块数量也为 $O(M)$,我们希望一次能够令一个点上跳一个块。
假设点 $u$,一次走的距离为 $i$($i\le 2M$)。
设 $db(u)$ 为到最近的不同块的祖先的距离,$du(u)$ 为到父亲的距离;
$rc(u, i)$ 为向上走一次能到达的最远的点;
$sp(u, i)$ 表示向上走最少几次能跳出块,$rm(u, i)$ 为最后一次会剩余多少未使用距离。
考虑步长为 $w$,当前向上跳的点为 $u$,根号分治:
- 对 $w\le 2M$,由于处理了 $sp, rm$,一次可以直接跳出一个块;
- 对 $w > 2M$,由于块数 $O(M)$,可以把一次移动拆成多次长为 $2M$ 的移动,一步只跳一个块。
预处理?对 $rc$,继承父亲的;对 $sp, rm$ 继承 $rc(u, i)$ 的。
嘛还有些讨论细节啥的,不过不重要。
反正这样就 $O(n\sqrt{n})$ 了。
参考代码
1 |
|