[2022.11.02] 模拟赛 第四题
给定一棵 个点的树,初始每条边长度都为 ,每次操作你需要选择一条边并令其长度增加 。
给定 次询问,每次给定一个数 ,你必须恰好完成 次操作,求操作后的最短直径。
首先找到树的中心,即直径的中点,但我们发现这个中点的位置可能在某个点上但也有可能落在某条边上。
为了解决这个问题,对于题目给定的任意一条边 和 ,我们加入一个新的节点 ,令 通过 与 相连。
这样,我们最后的答案就是 ,其中 是这棵树的直径,也就是说最后要求的变成了半径,而每次操作也就相当于将一条边的长度增加 。
这时候我们枚举一个点 ,设最终的树以点 为中心,找到距离其最远的一个叶节点,设两者之间的距离为 ,那对于这个中心点来说,要撑满 的半径,则要 次操作,其中 是叶节点的数量, 是点 到所有叶节点的距离和。
这不难理解,简单来说就是令 到每个叶子节点的距离都变成 ,同时可以证明通过不断加 一定能让距离不足 的叶节点距离刚好变为 。
那在这之后,对于一个以节点 为中心且值为 的答案,撑满这个答案需要的操作次数即为 ,即每次对所有叶子操作一次。
同时又注意到中心一定不可能是叶节点,否则我一定可以通过移动令答案更优,所以 是一个定值,也就是说我们的斜率是一定的。
我们可以通过一个简单的换根 求出不同节点的 以及初始的 ,即撑满 需要的操作次数。
这时候我们会得到若干个函数,以操作次数为横轴,以最终的答案为纵轴,每个函数由两部分组成,第一部分是一条水平的直线,这代表着撑满最初 的若干次操作,之后是一个斜率确定的一次函数,大致形状如下:
我们将所有询问从小到大排序,同时将所有函数封装成一个二元组 ,并按照 排序。
我们记录一个 和一个 ,表示回答上一个询问的答案以及它最多可以覆盖到的操作次数。
更新的时候若 ,则将函数 与当前答案进行比较,显然可以算出其在该询问下的最小答案以及其对应的最大操作次数,和 与 进行比较,若小于 ,则作为新的 和 ;若等于 ,则让 取最大值。
以上图为例,最开始我们加入函数 同时回答了 ,在回答 的时候我们发现函数 的答案也即当前 在 下超过了 ,这时我们将 加入讨论,比较后发现 在 的情况下一定是由于 的,且由于斜率不变,对于之后的所有 都会有 优于 ,于是我们舍弃掉 ,更新为 ;到 的时候我们又发现 比 更优秀。
重复以上过程。
最后需要注意的是, 的变化是不连续的,其只能在奇偶性相同的范围内进行变化,则有可能出现这样的情况,上一个询问中某个函数比上一个函数更优,但奇偶性变化后,另一个函数又更加优秀了。
针对这样的情况,我们把所有的函数分为初始的 是奇数与偶数分别进行上述计算,每个询问的答案取这两种情况结果的最小值即可。
本文作者:╰⋛⋋⊱๑落叶๑⊰⋌⋚╯
本文链接:https://www.cnblogs.com/Defoliation-ldlh/p/16854591.html
版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
2021-11-03 平衡树入门