信息学奥赛一本通-编程启蒙(C++版)在线评测系统
3431:【例75.2】 区间合并
解题思路
本题的核心是对给定的多个区间进行合并操作,判断最终能否合并成一个区间。可以按照以下步骤进行:
- 区间排序:首先将所有区间按照左端点从小到大进行排序。如果左端点相同,则按照右端点从小到大排序。这样做的目的是方便后续进行区间合并操作。
- 区间合并:遍历排序后的区间,从第一个区间开始,依次与后面的区间进行合并。如果当前区间的右端点大于等于下一个区间的左端点,说明这两个区间可以合并,更新当前区间的右端点为两个区间右端点的最大值。
- 结果判断:在遍历完所有区间后,如果最终只剩下一个区间,则输出该区间的左右端点;否则,输出 “no”。
C++ 代码实现
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
// 定义区间结构体
struct Interval {
int left;
int right;
};
// 自定义比较函数,用于对区间进行排序
bool compare(const Interval& a, const Interval& b) {
if (a.left == b.left) {
return a.right < b.right;
}
return a.left < b.left;
}
int main() {
int n;
cin >> n;
vector<Interval> intervals(n);
// 读取输入的区间
for (int i = 0; i < n; ++i) {
cin >> intervals[i].left >> intervals[i].right;
}
// 对区间进行排序
sort(intervals.begin(), intervals.end(), compare);
// 初始化合并后的区间
Interval merged = intervals[0];
// 遍历区间进行合并
for (int i = 1; i < n; ++i) {
if (merged.right >= intervals[i].left) {
// 可以合并,更新合并区间的右端点
merged.right = max(merged.right, intervals[i].right);
} else {
// 不能合并,说明无法合并成一个区间
cout << "no" << endl;
return 0;
}
}
// 输出合并后的区间
cout << merged.left << " " << merged.right << endl;
return 0;
}
代码解释
- 结构体
Interval
:用于表示一个区间,包含左端点left
和右端点right
。 - 比较函数
compare
:用于对区间进行排序,首先按照左端点从小到大排序,如果左端点相同,则按照右端点从小到大排序。 - 主函数
main
:- 读取输入的区间数量
n
,并创建一个存储区间的向量intervals
。 - 读取每个区间的左右端点,并存储到向量中。
- 使用
sort
函数对区间进行排序。 - 初始化合并后的区间
merged
为第一个区间。 - 遍历排序后的区间,依次与
merged
进行合并。如果可以合并,则更新merged
的右端点;如果不能合并,则输出 “no” 并结束程序。 - 遍历完所有区间后,输出合并后的区间的左右端点。
- 读取输入的区间数量
测试涵盖: 可以合并、不能合并、最小区间数量、最大区间数量以及所有区间相同等情况,能够全面测试代码的正确性。