Solution
令 $dis[u]$ 表示u到根节点的路径的”长度”并且满足 $dis[u]=edge(u,fa)-dis[fa]$ .
考虑可行路径u,v,他们的 $LCA$ 为 $lca$ ,则
如图,路径左侧表示的是$u$到$Root$路径上每一条边的长度的加减情况,可以得到,由于$(dep[u]-dep[v])\%2==0$ ,$Length(u,v) = dis[u]+dis[v]$ ,因此,我们只需要把所有的点按 $dep[]$ 的奇偶性分成两类,得到两个$dis$的数组,由于要求的是第$K$小的路径,我们二分答案的路径长度,然后求出有多少条路径”长度”小于等于 $limit$ (即 $mid$ )$ ,这一步可以用归并两个有序数组解决。
对奇数一组每个i,我们每次维护最后一个满足 $dis[i]+dis[j]<=lmt$ 的 $j$ ,由于两个数组均为有序,$i$ 向右推进的过程中,$j$ 一定会逐渐变小,因此问题即可解决。
|
|
个人总结
处理这一题的时候看到小数据为1000,直接暴力枚举可以达到$O(n^2)$,用dfs序即可,每次枚举节点$u$一个儿子的子树内的点与u子树中除该儿子外的子孙节点,表面上是$O(n^3)$ ,但是实际上是枚举点对,只有$O(n^2)$ 。
同时发现路径$(u,v)$的$Length$其实就等于$dis[u]+dis[v]$ ,那么我们就不需要枚举子树了,只需要求出所有点的$dis$ ,根据奇偶性放到两个数组里,枚举任意点对即可。
由于最后要求的是第$K$短的路径,一个比较可行的想法是二分,在边界上处理完了之后卡在了$check()$上,并没有想到可以归并求解,当时的目的是找到所有$dis[i]+dis[j]>=lmt$的点对$(i,j)$ 个数ans,并判断$ans>=K$是否成立,觉得应该可以用map什么的解决,但是时间已经不够了,思路越加混乱。
应该注意这类问题,往往和两个元素有关,可能是相加、相乘,这个时候可以考虑一下归并,一方面可以像这样二分求解,另一方面可以借用优先队列,在$K$有限的情况下存下所有的路径,每次找到最小的元素,具体如下:
刚开始存下所有的
$$a_1+b_1, a_1+b_2, .. ,a_1+b_n$$
然后每次取出最小的元素,再放进一个元素越靠近这个元素越好,不妨为$min(a_{i+1}+b_{j} , a_i+B_{j+1})$ ,这样能确保复杂度。
$By SongToy$