码迷,mamicode.com
首页 > 其他好文 > 详细

GMOJ 4289. Mancity 题解

时间:2020-07-19 23:40:42      阅读:67      评论:0      收藏:0      [点我收藏+]

标签:证明   man   倍增   https   细节   跳过   并查集   位置   优化   

义正言辞的吐槽出题人:漏题面就算了,大家一起被坑;数据范围写错也能忍,数据水;但把一道大量细节的题的题解写的如此简陋就实在……

于是有了这一篇同样简陋的东西。

约定

  1. 如无特殊说明,“点 \(i\) ” 指“当前点”或“某个点”。
  2. \(ToRt_i\) 表示 \(i\)\(Root\) 的实际距离
  3. 长度指要走多少小时,实际长度指路径上所有边的权值和

首先

先要知道两件事:

定理1:路径可逆性,即 \(x\to y\) 的答案和 \(y\to x\) 的答案一样。

定理2: 技术图片

如图,设绿色路径和黄色路径的长度均小于等于 \(d\) (注意,除非没有对应的红色路径或橙色路径,不能是0,原因后面讲),那么红色路径+蓝色路径+橙色路径的答案与 \(x\to y\) 的答案一样。

证明?没有证明,反正是对的

然后

因为我们有了定理2,所以我们尝试把询问拆成红色路径,橙色路径与蓝色路径来做。

因为有定理1,所以我们假定红色路径和橙色路径都是向上的。于是就有一种显然的方法,倍增每个点向上走的小时数,然后合并即可。但由于毒瘤出题人卡 \(O(nlogn)\) 算法,所以我们寻求优化。

注意到题目没有强制在线,考虑离线。

第一步,我们先求出每个点向上走1个小时能走到哪,设 \(T_i\) 为第 \(i\) 个点向上走1个小时走到的结点,明显的点 \(i\)\(T_i\) 肯定在 \(Root\)\(i\) 的路径上。然后,因为 \(i\)\(FA_i\) 有距离(废话),所以这个点的 \(T\) 一定在 \(T_{FA_i}\) (父亲的 \(T\))到 \(i\) 的路径上。

我们把 \(Root\)\(i\) 的路径用个栈记录一下,然后在这个栈上从 \(T_{FA_i}\) 所在的位置向后枚举一个 \(j\),直到 \(ToRt_i-ToRt_j\le D\) ,此时的 \(j\) 就是 \(T_i\)。因为每个点只会被枚举一次,所以时间复杂度 \(O(n)\)

接下来

正片现在开始。

首先我们如果要知道三大路径在哪,我们肯定要知道 \(LCA\) ,同样的,因为出题人卡 \(O(nlogn)\) 算法,所以需要使用离线的Tarjan算法求 \(LCA\)。什么?你不知道求 \(LCA\) 的Tarjan算法?戳我学习

接下来,我们想,对于红色路径,其可以从 \(x\) 跳若干次 \(T_x\) 得到,由于每个点只有一个 \(T\) ,所以 \(T\) 数组本身可以表示一棵树(即 \(T_i\) 表示 \(i\) 的父亲结点),设这棵树为 \(TreeT\)。设 \(x\) 的顶端为 \(Top\) ,因为每跳一次 \(T_x\) 就要消耗1小时,那么红色路径的长度就是在 \(TreeT\)\(x\)\(Top\) 的实际长度。

由于我们不知道 \(Top\) 的具体位置,所以我们不能直接处理。于是再DFS一遍,假设现在有一个点 \(i\)\(T_i\)\(m\) ,那么显然 \(i\)\(m\)\(TreeT\) 中的实际长度就为1,而 \(i\)\(TreeT\) 中的子树上的所有结点到 \(Root\) 的长度都要加1。 那么现在,\(i\) 与其子树到 \(m\) 的长度就可以计算。用并查集维护这棵树的关系,在并查集中额外维护 \(TreeT\) 中到 \(Root\) 的实际长度,采用路径压缩时,把其父亲所有点(可以包括 \(Root\),因为其值为0)的这个长度加到自己的长度再压缩(注意不能使用按秩合并,这样会破坏树的原本结构,路径压缩也破坏,但因为一开始的结构正确,可以维护正确的值)。这样就可以以 \(O(\alpha(N))\) 的时间复杂度维护所有 \(TreeT\) 的结点到 \(Root\) 的答案(实际高些,但无关紧要)。 我们在退出 \(i\) 时,把所有 \(T_j=i\) 的结点合并到 \(i\) 上来再回溯。

因为如果某个点跳过了 \(LCA\) ,那个点一定在 \(LCA\) 之上,所以在没有回溯 \(LCA\) 时,不会有点被合并到了 \(LCA\) 的上方。如果现在在 \(LCA\)\(x\)\(y\) 一定被合并到了 \(LCA\) 下方的某两个结点,这两个结点就是它们分别的 \(Top\) ,由于我们前面已经维护了路径长度,所以只要找到 \(Top\) (把长度处理出来,同时等会要用),那么就得到了红色路径和橙色路径的长度。

而对于蓝色路径,可以知道其实际长度一定小于等于 \(2\times D\)。那么如果其长度小于等于 \(D\),其一定花费1小时,如果其长度大于 \(D\) ,则一定花费2小时(当然有蓝色路径不存在的情况,此时 \(x=y\) ,需要特判一下)。蓝色路径的长度明显为 \(ToRt_{Topx}+ToRt_{Topy}-2\times ToRt_{LCA}\) ,把三条路径加起来,我们就可以得到答案了。

梳理

  1. \(LCA\)\(T\)

  2. 把所有的询问挂在 \(LCA\)

  3. DFS

    1. DFS所有子结点
    2. 处理所有被挂在这个点上的询问
    3. 把所有 \(T_i=\) 这个点的 \(i\) 合并到当前点上
  4. 输出

至于为什么先处理询问再合并(即黄色路径和绿色路径不能为0),请尝试以下数据:

4 3 1
1 2
2 2
2 1
3 4

GMOJ 4289. Mancity 题解

标签:证明   man   倍增   https   细节   跳过   并查集   位置   优化   

原文地址:https://www.cnblogs.com/groundwater/p/13341666.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!