1 条题解
-
0
题目理解
我们有 个区间 ,要选出 个区间,使得它们有公共交点(存在一个 被所有选中的区间包含)。
花费 = 被选中的区间中最长的长度 − 被选中的区间中最短的长度。
我们要最小化这个花费。
思路分析
1. 问题转化
如果我们选定了 个区间,它们有公共点 ,那么 一定属于这 个区间的交集。
为了最小化max_length − min_length,一个常见的思路是:- 将区间按长度排序。
- 使用**双指针(滑动窗口)**的方法,枚举最短区间和最长区间,并检查在长度区间 内能否选出 个区间有公共点。
2. 排序与双指针
我们按区间长度升序排序,这样我们枚举的区间在数组中是连续的,方便控制
max_len − min_len。假设排序后的区间序列是 (按长度从小到大)。
我们固定左指针 表示最短区间,右指针 表示最长区间,从 开始向右扩展 ,直到我们找到某个 使得在区间 中能选出 个区间有公共点。
3. 如何判断“m个区间有公共点”
这是一个经典问题:给定一堆区间,问是否存在一个点被至少 个区间覆盖。
我们可以用扫描线方法:
- 将每个区间 拆成两个事件:在 处覆盖数 +1,在 处覆盖数 −1。
- 按坐标从小到大扫描,维护当前覆盖数,如果某个时刻覆盖数 ,则存在公共点。
但这里我们是在区间集合 中做查询, 会变化,所以需要动态维护。
4. 动态维护区间覆盖数
当 增加时,加入区间 ;当 增加时,移除区间 。
我们可以用一个线段树或平衡树(因为坐标范围可能到 ,需要离散化)来维护:
- 区间加操作(加入区间时在 上加 1,删除时减 1)
- 全局最大值查询(即某个点的最大覆盖数)
如果全局最大值 ,说明当前 中存在一个点被至少 个区间覆盖。
5. 算法步骤
- 按区间长度排序。
- 离散化所有 (因为事件是 和 )。
- 双指针 。
- 当 :
- 不断右移 ,加入区间 (线段树区间加 1),直到当前覆盖最大值 。
- 如果满足,更新答案 。
- 右移 ,移除区间 (线段树区间减 1)。
- 输出答案(如果从未满足则输出 -1)。
时间复杂度:排序 ,双指针 ,每次操作线段树 ,总 。
6. 实现细节
- 离散化时注意 也要加入。
- 线段树维护区间加、全局最大值。
- 注意区间长度是 。
- 1
信息
- ID
- 4880
- 时间
- 3000ms
- 内存
- 256MiB
- 难度
- 10
- 标签
- 递交数
- 1
- 已通过
- 1
- 上传者