1 条题解

  • 0
    @ 2025-8-24 22:50:40

    自动搬运

    查看原文

    来自洛谷,原作者为

    avatar lzyqwq
    我永远喜欢数据结构。

    搬运于2025-08-24 22:50:40,当前版本为作者最后更新于2023-10-27 10:53:51,作者可能在搬运后再次修改,您可在原文处查看最新版

    自动搬运只会搬运当前题目点赞数最高的题解,您可前往洛谷题解查看更多

    以下是正文


    CNBLOGS

    洛谷

    • 给出一棵 nn 个点的树,边有边权。

    • dist(u,v)\text{dist}(u,v)u,vu,v 两点简单路径上的边的权值之和。

    • qq 次询问,每次询问给出 l,rl,r,求 minli<jrdist(i,j)\min\limits_{l\le i<j\le r} \text{dist}(i,j)

    • n2×105n\le 2\times 10^5q106q\le 10^6

    (i,j)(i<j)(i,j)\,(i<j) 为一个点对,若把 dist(i,j)\text{dist}(i,j) 看作改点对的权值,则我们要求解一个二维偏序问题。

    现在的问题就是点对太多了,一共有 O(n2)\mathcal{O}(n^2) 个。不过,真的需要这么多点对吗?比如现在有两个点对 (x1,y1)(x_1,y_1)(x2,y2)(x_2,y_2) 满足 x1x2y2y1x_1\le x_2\le y_2\le y_1dist(x1,y1)dist(x2,y2)\text{dist}(x_1,y_1)\ge \text{dist}(x_2,y_2),你发现若查询的区间包含了 (x1,y1)(x_1,y_1),就一定包含了 (x2,y2)(x_2,y_2),而且 (x2,y2)(x_2,y_2) 的权值更小。因此 (x1,y1)(x_1,y_1) 这个点对是没有用的。我们称 (x2,y2)\boldsymbol{(x_2,y_2)} 支配了 (x1,y1)\boldsymbol{(x_1,y_1)}

    我们称一个点对为支配点对,当且仅当它不被其他点对支配

    考虑找出一个集合 TT 包含所有的支配点对且大小可接受。我们来找一下一个点对成为支配点对的必要条件。

    考虑点分治,对于一个支配点对 (i,j)(i,j),则一定存在一个分治重心 rtrt 满足 i,ji,jrtrt 不同儿子的子树中。不妨钦定 dist(i,rt)dist(j,rt)\text{dist}(i,rt)\le \text{dist}(j,rt)。设 SS 表示当前联通块中满足 dist(x,rt)dist(j,rt)\text{dist}(x,rt)\le \text{dist}(j,rt)xjx\ne jxx 构成的集合,i\boldsymbol{i} 一定是 S\boldsymbol{S} 中最大的 <j\boldsymbol{<j} 的数(前驱)或最小的 >j\boldsymbol{ >j} 的数(后继)

    为什么?考虑反证法,以前驱为例,设 jj 的前驱为 prepre,若 i<prei<pre,根据 SS 的定义可知 $\text{dist}(i,rt),\text{dist}(pre,rt)\le \text{dist}(j,rt)$。

    此时一定满足:

    • $\text{dist}(i,pre)\le \text{dist}(i,rt)+\text{dist}(pre,rt)\le \text{dist}(i,rt)+\text{dist}(j,rt)=\text{dist}(i,j)$。

      $\text{dist}(i,pre)\le \text{dist}(i,rt)+\text{dist}(pre,rt)$ 是因为相较于后者前者要减去根到 LCA\text{LCA} 路径的边权和。

    • i<pre<ji<pre<j

    你发现 (i,j)(i,j)(i,pre)(i,pre) 支配了。后继的证法类似,此处不再赘述。

    考虑这样一个过程,对于每一层点分治,对于每一个点维护集合 SS,并找到前驱、后继并将该点对加入 TT。那么任意一个支配点对 (i,j)(i,j),点分治进行到使得它们在两棵不同子树中的联通块时,因为 ii 一定是前驱或后继,那么对于 jj 这个点找前驱、后继的时候,就把这个点对找到了。所以这样找到的 T\boldsymbol T 集合包含了所有支配点对。

    并且,由于点分治只会进行 O(logn)\boldsymbol{\mathcal{O}(\log n)} 层,每一层每个点带来 O(1)\boldsymbol{\mathcal{O}(1)} 个点对,因此找到的总点对数量为 O(nlogn)\boldsymbol{\mathcal{O}(n\log n)}

    具体地,如何实现这个构造 TT 的过程?对于每一个联通块的点分治,将所有点 uu 按照编号升序排序。正着反着扫一遍,维护一个随着 uu 递增 / 递减,dist(u,rt)\text{dist}(u,rt) 不降的单调栈。那么对于一个点 vv,它就是被它出栈的那些点的前驱 / 后继。

    我们已经得到了集合 TT,那么拿 TT 中的点对去做二维数点即可。考虑离线 + 倒序扫描 ii 保证 lil\le i,用树状数组维护 jrj\le r 求前缀最值即可。至于 dist(i,j)\text{dist}(i,j),用树剖 + LCA\text{LCA} 求一下即可。

    时间复杂度为 O(nlog2n+qlogn)\mathcal{O}(n\log^2 n+q\log n),空间复杂度为 O(nlogn+q)\mathcal{O}(n\log n+q)

    提交记录 代码

    • 1

    信息

    ID
    9264
    时间
    4000ms
    内存
    512MiB
    难度
    7
    标签
    递交数
    0
    已通过
    0
    上传者