1 条题解
-
0
题目理解
我们有 个区间 ,定义从区间 可以跳到区间 的条件是:
[ r_x \in [l_y, r_y] ]
即当前区间的右端点必须落在目标区间的范围内。
给定 次询问,每次给出起点区间编号 和终点区间编号 ,要求输出从 到 的最少跳跃次数,若无法到达则输出
impossible。
关键观察
-
图论建模
可以将每个区间看作图中的一个节点,如果 ,则建立一条从 到 的有向边。那么问题转化为在有向图上求 到 的最短路径(边权为 1)。 -
直接建图的复杂度问题
最大可达 ,如果直接枚举所有 的边对会超时。因此必须优化建图。 -
贪心跳跃策略
假设当前在区间 ,右端点为 。在所有能跳到的区间中(即 ),选择 右端点 最大 的区间跳,可以覆盖更远的距离,从而减少跳跃次数。
这种贪心类似于在一条数轴上,每次选择能覆盖当前位置且延伸最远的区间。 -
跳跃的单调性
在贪心策略下,跳跃序列的右端点是单调不减的(实际上严格递增,除非出现相同右端点)。因此,如果 ,则一定不可能从 到达 (因为右端点只会增加或不变,但这里不变的情况很少,因为要跳到不同的区间)。
解题思路
1. 预处理“下一个”跳跃
对每个区间 ,我们想快速知道:从它出发,按照贪心策略(右端点最大)能跳到的下一个区间是哪个。
具体做法:
- 将区间按左端点 排序(左端点相同则按右端点从大到小)。
- 用数据结构(如线段树或 ST 表)维护区间右端点的最大值,对于给定的 ,在所有满足 的区间中,找到 最大的区间 (且 ,除非允许自环,但这里通常不允许)。
这样我们可以为每个区间 预先计算出
next[i],表示从 出发贪心一跳能到达的区间。2. 倍增优化查询
由于 和跳跃次数可能很大,我们使用 倍增法(Binary Lifting)来快速模拟多次跳跃。
定义:
jump[i][k]表示从区间 出发,贪心跳 步后到达的区间。- 初始
jump[i][0] = next[i]。 - 转移:
jump[i][k] = jump[ jump[i][k-1] ][k-1]。
3. 处理询问
对于询问 :
- 如果 ,答案是 。
- 如果 ,输出
impossible(因为右端点不会减少)。 - 否则,先从 贪心跳若干步,使得跳完后的区间 满足 ,并且步数尽量少。
- 具体方法:从高到低尝试倍增的幂 ,如果
jump[s][k]的右端点仍小于 ,就跳这 步。
- 具体方法:从高到低尝试倍增的幂 ,如果
- 此时再判断:
- 如果 或者从 可以直接一步跳到 (即 ),则得到总步数。
- 否则可能需要再多跳一步:因为贪心路径可能跳过 ,所以先跳到 ,再检查
next[p]是否能到 。
复杂度分析
- 排序:
- 预处理每个区间的
next[i]: - 倍增预处理:
- 每个询问:
总复杂度:,可以处理 的数据。
总结
这道题的核心是将区间跳跃问题转化为图的最短路问题,并利用 贪心选择右端点最大 的区间来减少边数,再通过 倍增法 快速模拟多次跳跃,从而高效回答询问。
关键点在于理解跳跃的单调性和贪心最优性,并熟练运用数据结构与倍增技巧。 -
- 1
信息
- ID
- 3711
- 时间
- 1000ms
- 内存
- 256MiB
- 难度
- 10
- 标签
- 递交数
- 1
- 已通过
- 1
- 上传者