考虑特殊性质 A,即序列上的问题怎么做。观察一下每次我们会怎么移动,如果要求点 x 移动到区间 [l,r],如果 x<l,会移动到 l;如果 x>r,会移动到 r;否则不会移动。这给我们的启示是,如果移动了,本质不同的终点集合是非常少的。基于这个性质,我们能够得到如下做法。对于所有 (p,i) 二元组,其中 p 是 l_i,r_i 之一,处理出点 p 依次执行 [i+1,m] 的所有操作,第一次会在编号为多少的操作处移动,或者到最后也不会移动。这可以线段树二分简单算出。同理,在线回答任意点 p 在依次执行 [l,r] 中所有操作的时候第一次在哪个操作处移动也是简单的。倍增地计算这个过程,同时记录移动的总步数,可以得到答案。
考虑特殊性质 B 怎么做。我们将直径中点设为根,可以证明,每次操作都只会让一个点的深度减小。于是对于一个询问 (p,l,r),我们要求的,就是 \max(\max_{i\in[l,r]}\operatorname{dis}(p,a_i)-d_i,0)。类似带权直径的结论,我们只需找到一对 (u,v)\in[l,r] 最大化 \operatorname{dis}(a_u,a_v)-d_u-d_v,答案就一定是 \max(\operatorname{dis}(p,a_u)-d_u,\operatorname{dis}(p,a_v)-d_v,0)。使用线段树维护带权直径即可快速回答询问。
我们考虑如何拓展上述两档特殊性质来得到对一般的树上问题的解法。
首先将树定根。我们定义一个邻域的顶为这个邻域中深度最小的节点。显然一个邻域的顶唯一。我们的目标点如果不在根到当前点的链上,一定是一个邻域的顶。于是我们的移动过程一定可以划分为若干段,形如:向上跳若干步祖先,走到某个邻域的顶,向上跳若干步祖先……。观察有没有性质 A 类似的性质,我们惊喜地发现:如果一次操作向下移动了,那么终点是唯一的,一定是一个顶!如果我们能在线回答若干询问,形如从点 p_i 开始,依次执行 [l_i,m] 中的所有操作,第一次到达某个顶是什么时候,以及中间走了多少步,那么进行性质 A 的倍增,结束之后再做一个性质 B,就可以得到答案。
对这个分两种情况。第一种是 p 在目标顶的子树外,这种贡献可以在主席树上查 min 做。第二种是 p 在目标顶的子树内,如果我们能对每个邻域 i 的顶预处理出最大的 j<i 使得 j 的顶是 i 的顶的祖先且邻域 j 不包含 i 的顶,那么做前后缀主席树可以回答询问。
重申一下,我们希望维护数据结构,支持以下操作:在树上标记一个邻域;询问给一个点 p,求编号最大的邻域,不包含 p 且顶是 p 的祖先。考虑离线,倒着扫时间轴,我们存储所有还没有被回答的询问点,每次加入邻域的时候,我们只需找到顶的子树内距离邻域中心最远的询问点,判断这个点能不能被当前邻域匹配即可。线段树维护区间直径可以找到这个点。这部分的复杂度是均摊的 1log。