雨林跳跃[APIO2021]

https://www.luogu.com.cn/problem/P7599

题解

考虑找到 (B,C) 区间内的最高树 M[C,D] 中的最高树 N

那么最后一步跳跃一定是从某棵满足 {HMHTHN} 且 {(T,M) 中没有比 T 更高的树} 的树 T 跳进 [C,D] 区间中

我们把所有这样的树 T 叫做"准终点"

所以原问题的目标就等价于用最少的步数跳到一个准终点上 然后再跳一步进入 [C,D]

[A,B] 中的哪棵树开始?

如果 [A,B] 中存在一个准终点,那么显然可以直接从那棵树出发,只需一步即可完成

否则,最优方案应该从 [A,B] 中满足 {(P,M) 中没有比 P 更高的树} 的树中最高的那棵 P 开始 下面给出证明

如图,RP 向左跳一次到的那棵树,Q 是向右跳一次到的那棵树

由于上文假设 [A,B] 中没有合法的准终点 ,所以树 R 比 树 N 更高,所以向右跳一次一定会到达 D 右边,因此 [A,R] 区间的树都不能作为起点

对于 (R,P) 区间的树,它们的高度全部小于 H[P]。如果想要跳出 (R,P) 区间,不论怎么跳都会到达 R,P 其中一棵树,一定没有从 P 开始优

对于 (P,Q) 区间的树同理,一定会跳到 P,Q 其中一棵树,然而 P 只需一步就能跳到 Q ,所以一定没有 P 优秀

所以从 P 出发一定最优,QED

如何找到最优出发点?

从第 B 棵树开始,倍增地向左跳,跳到最左边的一棵在 A 之前并且高度小于树 N 的树,它就是最优出发点

如果它是准终点,那么只需一步,否则需要多步

P 出发怎么跳最优?

对于一棵树,可以向左跳或者向右跳,我们把跳到左右中较高的一棵树称作跳高边,反之叫跳低边

有如下跳的策略:

  • 如果当前树既可以向左跳又可以向右跳,并且向左右跳到的树高度都小于树 M ,那么优先跳高边(我们希望用尽量少的步数使当前高度增加)
  • 如果某时刻跳高边会使得跳到的树高度大于等于树 M ,那么验证一下跳高边到的那棵树是否是一个准终点,如果是那么就直接跳到它
  • 否则就总是向右跳,跳到一个准终点为止(如果跳不到说明无解)

容易发现这就是最优策略

实现时先从最优出发点出发,倍增跳高边跳到最高的一棵高度小于树 M 的为止 假设是树 X

检查从 X 跳高边到的那棵树是不是准终点

如果不是,那就从 X 出发倍增向右跳跳到最高的一棵高度小于树 M 的为止,然后检查它向右跳一步是不是准终点

所有的步骤都可以使用ST表或者倍增实现,所以总时间复杂度是 O((n+q)logn)

posted @   AK_DREAM  阅读(150)  评论(0编辑  收藏  举报
编辑推荐:
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
阅读排行:
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 使用C#创建一个MCP客户端
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列1:轻松3步本地部署deepseek,普通电脑可用
· 按钮权限的设计及实现
点击右上角即可分享
微信分享提示