区间选点
题目描述
给定 N 个闭区间 [ai,bi],请你在数轴上选择尽量少的点,使得每个区间内至少包含一个选出的点。
输出选择的点的最小数量。
位于区间端点上的点也算作区间内。
输入输出及样例
最大不相交区间
题目描述
给定 N 个闭区间 [ai,bi],请你在数轴上选择若干区间,使得选中的区间之间互不相交(包括端点)。
输出可选取区间的最大数量。
输入输出及样例
注
此处的最大不相交区间的相交不包括包含关系,即,如果一个大区间里面完全包含着一个小区间,那么二者是包含关系而非相交关系。
思路
过这两道题的代码是一样的,都是以贪心的思想对区间进行排序来解题。
①对于区间选点,维护区间信息,即使用一个结构体或pair记录区间的l和r,存储在数组中。使用sort对数组进行排序,以起点l的大小值对区间进行升序排序,这样,“开始的早”的区间排在了前面。
②维护ed作为“end”,即“断点”,这个值的初始值是第一个区间的右端点r。当第二个区间(它的起点一定“开始的比第一个区间晚或同时开始”)的起点l大于end时,说明出现了断点,需要为下一个区间增加一个点,来满足题意。同时更新end,更新为当前贡献断点的区间的右端点。
③如果没有出现断点,仍需要维护ed的值,即,令ed = min(ed, p[i].y)
,原因是可能出现了包含关系,即当前ed的区间完全包含了后面这个区间,ed的值应该更新为被包含区间的右端点。
④最大不相交区间的思考过程即为区间选点的逆过程,因为每个不相交的位置,都应该选出一个点。
代码
#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std;
const int maxn = 1e5 + 5;
struct xy{
int x, y;
}p[maxn];
int n;
inline bool cmp(const xy &p1, const xy &p2){
return p1.x < p2.x;
}
int main()
{
ios::sync_with_stdio(false);
cin.tie(0);
cin>>n;
for(int i=1;i<=n;i++){
cin>>p[i].x>>p[i].y;
}
sort(p+1, p+1+n, cmp);
int ed = p[1].y;
int res = 1;
for(int i=2;i<=n;i++){
if(p[i].x > ed){
res ++;
ed = p[i].y;
}
else{
ed = min(ed, p[i].y);
}
}
cout<<res;
return 0;
}