步行(walk.cpp)

【题目描述】

小C喜欢步行,只有缓慢的步行,小C才能沉浸于其中,享受旅途中那些美好的瞬间。

小C来到了一座新的城市生活,这座城市可以看成 \(n\) 个点, \(n−1\) 条长度为1的无向边连接 的连通图,也就是说这个城市的结构是一棵树。小C计划在这个城市旅行,他对这个城市的 每一个节点都进行了初步的了解,并制定了一个旅行计划,他按照自己的兴趣等因素,为每 一个节点设定了游览次数 \(v_i\) ,表示他计划在第 \(i\) 个节点游览多少次。

在这之后,小C想要找出一个游览序列。游览序列是一个长度为\( = \sum v_i\) 的序列,对于 \(i \in [1,n]\) , \(i\) 在序列中出现vi次,设这个序列为 $ A$ 。确定序列后小C将会沿着 $ A_1,A_2,...,A_S$ 的顺序 步行游览,每次从一个点走最短路径到下一个点,并最终从AS返回 \(A_1\) ,游览序列中相邻的 两位以及,1可以相同,这个时候小C的步行距离为0。小C喜欢步行,因此他希望他的总步 行距离尽可能长。

小C发现这一座城市还会时常发生交通管制事件,在这样的情况下,一条原有的道路会无法通行,还会有一条临时道路出现,管制过程中这座城市依旧连通。小C会告诉你m次这 样的事件,希望你告诉他在这m种管制情况下,他的最长步行距离分别是多少。然而小C的信息也有可能是错的,例如无法通行的道路不存在,或者管制后的城市不连通,这时你需要告诉他这条信息是错误的。

题目大意:

一棵树,求一个每个点出现特定次数的序列,使得这个序列相邻的两位之间, 包括最后一位与第一位之间的距离之和最大。每次去掉一条边加上一条边询问。

3.1 算法 1

暴力枚举游览序列,查询树上距离。

时间复杂度 \(O(S!nm)\)。

期望得分8分。3.2 算法 2

考虑树形 dp,令 \(f_{i,j}\) 表示i号点的子树里面的所有点在序列中构成j个连续段,子树内步行距离和最大值。转移时枚举两个子树,以及有多少段合并起来了。

时间复杂度 \(O(mS_3)\) 。

期望得分16分。

3.3 算法 3

观察到每条边走的次数是把这条边断掉之后,出现次数和较小的连通块的出现次数和的两倍。

答案显然不可能超过这个值,构造也比较容易,找到树的带权重心,权为每个点出现次数,这样所有边断掉之后较大的连通块都包含重心。接下来就是把重心去掉,每个部分的出现次数之和都不超过 \(S2\) ,容易构造出一种序列使得相邻两位都不来自相同的连通块, 这样就达到了这个最大值。

既然有了这个结论,每次 dfs 算出子树和就可以得到答案了。

时间复杂度 \(O(nm)\)

期望得分36−44分。

3.4 算法 4

可以发现,如果按照每条边来算贡献的话,那么在添加的道路两个端点对应原树的路径上的边贡献会改变,其他的均不会改变。因为树是完全二叉树,两点之间边数只有\(O(log⁡(n))\) 级别,暴力计算即可。

时间复杂度 \(O(n+mlog(n))\) ,结合前面的算法。

期望得分44−52分。

3.4 算法 5

如果树是一条链,那么修改一条边之后也只会是一个“T”状图。在这个“T”状图上

二分重心的位置,然后计算对应部分的贡献。

时间复杂度\(O(n+mlog(n))\)。

结合前面的算法,期望得分52−64分。

3.6 算法 6

首先当n较大的时候,信息错误使用倍增 lca 代替暴力判断即可 。

信息正确时,只需要延续算法 5 的思路,不妨把新添加的边端点在原树上的对应链提出来,加上新添加的边构成一个环。整棵树就变成了环套树。把环以外的所有边的贡献先算出来,这个可以通过子树和的方式计算。然后把环外面每个点的出现次数都加到对应的环上的点上面。这样问题就变成了一个环断掉一条边,答案是多少。采用算法 5 的二分方法,不过在这里是使用倍增数组进行二分。实现良好的话可以通过。

时间复杂度\(O((n+m)log⁡(n))\)。

期望得分68−100分。

步行(walk.cpp) noip模拟的更多相关文章

  1. NOIP模拟赛20161022

    NOIP模拟赛2016-10-22 题目名 东风谷早苗 西行寺幽幽子 琪露诺 上白泽慧音 源文件 robot.cpp/c/pas spring.cpp/c/pas iceroad.cpp/c/pas ...

  2. 2016-06-19 NOIP模拟赛

          2016-06-19 NOIP模拟赛 by coolyangzc 共3道题目,时间3小时 题目名 高级打字机 不等数列 经营与开发 源文件 type.cpp/c/pas num.cpp/c ...

  3. 8.22 NOIP 模拟题

      8.22 NOIP 模拟题 编译命令 g++ -o * *.cpp gcc -o * *.c fpc *.pas 编译器版本 g++/gcc fpc 评测环境 位 Linux, .3GHZ CPU ...

  4. 2019.6.20 校内测试 NOIP模拟 Day 1 分析+题解

    这次是zay神仙给我们出的NOIP模拟题,不得不说好难啊QwQ,又倒数了~ T1 大美江湖 这个题是一个简单的模拟题.   ----zay 唯一的坑点就是打怪的时候计算向上取整时,如果用ceil函数一 ...

  5. NOIP模拟17.9.21

    NOIP模拟17.9.21 3 58 145 201 161.5 样例输出21.6 数据规模及约定对于40% 的数据,N <= 20对于60% 的数据,N <= 1000对于100% 的数 ...

  6. NOIP模拟17.9.22

    NOIP模拟17.9.22 前进![问题描述]数轴的原点上有一只青蛙.青蛙要跳到数轴上≥

  7. NOIP模拟赛 6.29

    2017-6-29 NOIP模拟赛 Problem 1 机器人(robot.cpp/c/pas) [题目描述] 早苗入手了最新的Gundam模型.最新款自然有着与以往不同的功能,那就是它能够自动行走, ...

  8. NOIP模拟 6.28

    NOIP模拟赛6.28 Problem 1 高级打字机(type.cpp/c/pas) [题目描述] 早苗入手了最新的高级打字机.最新款自然有着与以往不同的功能,那就是它具备撤销功能,厉害吧. 请为这 ...

  9. NOIP模拟 17.8.15

    NOIP模拟17.8.15 A 债务文件名 输入文件 输出文件 时间限制 空间限制debt.pas/c/cpp debt.in debt.out 1s 128MB[题目描述]小 G 有一群好朋友,他们 ...

随机推荐

  1. Redis笔记(一)

    redis:1.什么是缓存? mybatis一级缓存和二级缓存 mybatis的一级缓存存在哪? SqlSession,就不会再走数据库 什么情况下一级缓存会失效? 当被更新,删除的时候sqlsess ...

  2. GUI常用监听事件

    概念 对鼠标.键盘等一系列事件做出相应的反馈 事件监听 //创建监听事件 public class Demo { public static void main(String[] args) { Fr ...

  3. K8S集群架构的组件组成

    1.Master--主控节点 (1)apiserver:集群统一入口,以restful的方式,交给etcd存储 (2)scheduler:节点调度,选择node节点应用部署 (3)controller ...

  4. Dockerfile优化——supervisor服务

    一.理解supervisor(supervisor服务不仅在容器中可用,在宿主机中也适用) 1.Dockerfile中的CMD可以指定启动容器后执行的第一个命令,但是当有多个服务进程需要启动的时候,就 ...

  5. 在vue-cli项目中定义全局 filter、method 方法

    1.创建 filters.js(methods.js) 文件: 2.filters.js(methos.js) 中定义全局过滤方法: 1 export default { 2 /** 时间戳转换 */ ...

  6. 关于Container容器以及IoC注入机制的认识

    container 容器的概念: 1 container 是一个Java 所编写的程序,用于对象之间之间管理对象关系. 主要的java EE 容器如下: Java容器类包含List.ArrayList ...

  7. 重学VUE——vue 常用指令有哪些?

    一.什么是指令? 在 vue 中,指令以 v- 开头,是一种特殊的自定义行间属性.指令属性的预期值是一个表达式,指令的职责就是:表达式的值改变时,相应地将某些行为应用到DOM上.只有v-for是一个类 ...

  8. xml字符串转成数组(php)

    1 $str = '<xml> 2 <ToUserName> <![CDATA[gh_fc0a06a20993]]> </ToUserName> 3 & ...

  9. Java基础系列(39)- 二维数组

    多维数组 多维数组可以看成是数组的数组,比如二维数组就是一个特殊的一维数组,其每一个元素都是一个一维数组. 二维数组 int a[][]=new int[2][5]; 解析:以上二维数组a可以看成一个 ...

  10. Ubuntu怎么开启/关闭防火墙

    在Ubuntu中,使用sudo ufw status命令查看当前防火墙状态. 不活动,是关闭状态. 在Ubuntu中,使用sudo ufw enable命令来开启防火墙. 在Ubuntu中,使用sud ...