P14211-路径问题的处理

P14211 快递服务

题意:

给你一颗 \(n\) 个节点的树,和树上的 \(q\) 条路径,求一个路径对,使得这两条路径的交的长度最大。

\(n,q\le 2\times 10^5\)

解法:

观察一下路径交的性质,大致将路径分为两类:

  • \(lca\) 相同的路径

  • \(lca\) 不同的路径

链:

对于后者,发现两条路径交一定是一条直链。

对于这种路径交为直链且链的一端已知的情况,我们想要快速的求出这条路径与其他路径的交的最大值。那么有个套路就是:

  • 用 \(multiset\) 去维护路径的另一端(按照 \(dfs\) 序排序)。

  • 查询时找到路径某一端 \(v\) 的前驱后继, 然后分别找到 \(v\) 与前驱和后继的 \(lca\) ,取其中深度更大的一个。

如红色路径,已知路径交链顶一端一定为 \(3\) 号节点。红色路径某一端点 \(5\) 的前驱是 \(4\) 号节点,后继是 \(5\) 号节点。则查找 \(lca(4,5)=4\) , \(lca(7,5)=5\) , 去深度最大的节点 \(5\) 作为路径交的链的右端点。

\(sol\) :直接在树上按照路径 \(lca\) 的 \(dfs\) 序处理,结合刚刚的 \(multiset\) 。

共 \(lca\) :

对于 \(lca\) 相同的路径,路径交是折线 。那么显然对每个点分别处理所有 \(lca\) 是该点的路径。

这里有两种思考方式:

  • 枚举每条路径,快速找另一条路径使得其与该路径的交的长度最大。

  • 枚举路径交的一段,快速找到路径交另一端的最大深度。

显然,第一种直接 \(out\) ,因为虽然这种情况下两条路径的交可以 \(O(1)\) 算出来,但多条路径还是 \(O(n^2)\) 没法优化。

那么思考第二种,第二种实际上是在降维,降成只用考虑路径交为直链的情况(即情况一)。

显然我们可以先建出虚树,然后再虚树上枚举路径交(这和原问题是等价的)。

那么考虑怎么融合情况一。

假设枚举到了 \(x\) ,则需要把 \(x\) 子树里面的路径的另一端都加入 \(multiset\) 。然后查询相邻两个数的 \(lca\) 的深度。

但显然,如果直接这样枚举的话,时间复杂度是 $O(n^2\log n) $的,不可接受。

但其实你会发现这个过程实际上是树上的一个合并过程,即把当前节点儿字子树内的路径端点都加入到当前节点的 \(multiset\) 中。

这可以用树上启发式合并解决。显然我没想到 。

这样这道题就做完了。

如果使用 \(O(1)\) \(lca\) 的话 ,时间复杂度就是 $O(n\log^2n) $ 。(假设 \(n\) ,\(q\) 同阶 )

posted @ 2026-10-11 15:59  wlhao  阅读(6)  评论(0)    收藏  举报