题目
给定 N 个闭区间 [ a i , b i ] [a_i,b_i] [ai,bi],请你在数轴上选择尽量少的点,使得每个区间内至少包含一个选出的点。
输出选择的点的最小数量。
位于区间端点上的点也算作区间内。
输入格式
第一行包含整数 N ,表示区间数。
接下来 N 行,每行包含两个整数 a i , b i a_i,b_i ai,bi,表示一个区间的两个端点。
输出格式
输出一个整数,表示所需的点的最小数量。
数据范围
1 ≤ N ≤ 1 0 5 , − 1 0 9 ≤ a i ≤ b i ≤ 1 0 9 1≤N≤10^5,\\ −10^9≤a_i≤b_i≤10^9 1≤N≤105,−109≤ai≤bi≤109
输入输出样例
样例输入1
3
-1 1
2 4
3 5
样例输出1
2
思路
贪心。
算法分析
- 将每个区间按右端点从小到大排序。
- 从前往后依次枚举每个区间,设ed为每个区间选择的点,初始化值为无穷小。
- 若当前区间中已包含点 PASS
range[i].l > ed
-否则选择当前区间的右端点ed = range[i].r
- 若当前区间中已包含点 PASS
证明
令ans为所有可行解的最小值,cnt为一个可行解方案。
- 由于题意是找出选择的点的最小数量,即
ans ≤ cnt
- 若已有cnt个两两互不相交的区间,则所有方案都要把它们覆盖住,那么至少需要cnt个点,即
ans≥cnt
证明出ans = cnt
。
C++ operator关键字(重载操作符)链接
代码
#include<iostream>
#include<algorithm>
using namespace std;
const int N = 1e5 + 10;
int n;
struct Range
{
int l, r;
bool operator < (const Range &w) const
{
return r < w.r;
}
}range[N];
int main()
{
scanf("%d",&n);
for(int i = 0; i < n; i++)
{
int l, r;
scanf("%d%d", &l, &r);
range[i]={l, r};
}
sort(range, range + n);
int res = 0, ed = -2e9;
for(int i = 0; i < n; i++)
{
if(range[i].l > ed)
{
res++;
ed = range[i].r;
}
}
printf("%d",res);
return 0;
}