1. 题目背景与理解
1324题"整数区间"是《信息学奥赛一本通》中的经典题目,主要考察选手对贪心算法和区间问题的理解和应用能力。这类题目在NOIP/CSP等竞赛中频繁出现,是必须掌握的基础算法题型。
题目通常会给出若干个闭区间[a,b],要求选择最少数量的点,使得每个区间至少包含一个被选中的点。例如给定区间[1,3]、[2,4]、[3,5],最优解是选择点2和4,这样每个区间都至少包含一个点。
注意:这类问题在实际编程竞赛中往往不会直接给出这样明确的描述,可能会隐藏在更复杂的情景背后,因此识别问题本质是关键。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 问题分析与算法选择
2.1 问题转化与建模
我们需要将实际问题转化为数学模型。给定n个区间,每个区间表示为[l_i, r_i],要求找到最小点集S,使得对于每个区间,都有S∩[l_i, r_i]≠∅。这等价于找到最少的点覆盖所有区间。
2.2 贪心算法思路
这个问题可以使用贪心算法高效解决,其正确性基于以下观察:
- 如果将区间按右端点排序,那么选择第一个区间的右端点可以覆盖所有与之相交的区间
- 剩下的未覆盖区间不会与已选点相交,可以递归处理
算法时间复杂度为O(nlogn),主要来自排序操作,后续处理是线性的。
3. 算法实现细节
3.1 数据结构设计
首先需要定义区间结构体:
cpp复制struct Interval {
int l, r;
bool operator < (const Interval &t) const {
return r < t.r; // 按右端点排序
}
};
3.2 核心算法步骤
实现贪心算法的主要步骤:
- 将所有区间按右端点升序排序
- 初始化已选点集为空,当前覆盖位置为负无穷
- 遍历每个区间:
- 如果当前区间左端点 > 当前覆盖位置
- 选择该区间的右端点加入点集
- 更新当前覆盖位置为该右端点
3.3 完整代码实现
cpp复制#include <iostream>
#include <algorithm>
using namespace std;
const int N = 10010;
struct Interval {
int l, r;
bool operator < (const Interval &t) const {
return r < t.r;
}
} intervals[N];
int main() {
int n;
cin >> n;
for (int i = 0; i < n; i++)
cin >> intervals[i].l >> intervals[i].r;
sort(intervals, intervals + n);
int res = 0, pos = -2e9;
for (int i = 0; i < n; i++) {
if (intervals[i].l > pos) {
res++;
pos = intervals[i].r;
}
}
cout << res << endl;
return 0;
}
4. 算法正确性证明
4.1 贪心选择性质
我们需要证明每次选择当前最右区间的右端点是最优选择。假设存在一个最优解,它没有选择第一个区间的右端点,而是选择了某个点p < r1。我们可以将p替换为r1,仍然保持解的有效性,且不会增加点数。
4.2 最优子结构性质
在选择了一个点后,剩下的问题是在未被覆盖的区间上寻找最小点集,这与原问题具有相同的结构。因此可以通过归纳法证明整个算法的正确性。
5. 变种与扩展问题
5.1 区间分组问题
类似的问题还有将区间分成尽可能少的组,使得每组内的区间两两不相交。这可以通过类似的贪心策略解决,但需要使用优先队列来维护各组的最右端点。
5.2 最大不相交区间问题
选择尽可能多的互不相交的区间。这实际上是本问题的对偶问题,同样可以用贪心算法解决,只需选择尽可能早结束的区间。
5.3 带权区间问题
如果每个区间有权值,要求选择点使得被覆盖区间的权值和最大,这就变成了更复杂的动态规划问题。
6. 竞赛中的实战技巧
6.1 输入输出优化
在竞赛中处理大规模数据时:
cpp复制ios::sync_with_stdio(false);
cin.tie(0);
6.2 边界条件处理
特别注意区间端点可能为负数的情况,初始化pos时应使用足够小的值(如-2e9)。
6.3 调试技巧
可以打印中间结果验证算法行为:
cpp复制cout << "Selected point at " << pos << endl;
7. 性能分析与优化
7.1 时间复杂度
排序O(nlogn) + 线性扫描O(n),总体O(nlogn)。这在n≤1e5时完全可行。
7.2 空间优化
如果不需要保留原始区间,可以在读取时直接处理,将空间降到O(1)。
7.3 并行化可能
排序阶段可以使用并行排序算法,但实际竞赛中很少需要。
8. 常见错误与陷阱
8.1 排序方式错误
如果错误地按左端点排序,会导致算法失效。例如区间[1,4],[2,3],按左端排序会选择4,实际只需选择3。
8.2 端点处理不当
开区间和闭区间处理不同,题目明确要求闭区间时不要混淆。
8.3 变量初始化错误
pos初始值必须小于所有可能的区间左端点,否则可能漏选第一个区间。
9. 实际应用场景
这类算法在现实中有着广泛应用:
- 课程安排:在有限教室安排最多课程
- 资源分配:最小资源满足所有请求
- 传感器覆盖:最少传感器覆盖所有区域
10. 进阶学习建议
- 证明其他贪心算法的正确性
- 学习网络流中的区间覆盖模型
- 研究动态规划解法及其优化
- 尝试在线算法版本,区间动态增加的情况
我在实际解题中发现,这类区间问题虽然看似简单,但能很好地训练算法思维。建议初学者手动模拟几个例子,真正理解为什么贪心策略有效。竞赛中遇到类似问题时,首先要准确识别问题类型,然后套用已知算法,最后仔细处理实现细节。
