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\) 同阶 )

浙公网安备 33010602011771号