区间选点
贪心问题——找局部最优解(只有一个问题是单峰的时间,才可以用贪心算法)
题目
给定 N 个闭区间 [ai,bi],请你在数轴上选择尽量少的点,使得每个区间内至少包含一个选出的点。
输出选择的点的最小数量。
位于区间端点上的点也算作区间内。
输入格式
第一行包含整数 N,表示区间数。
接下来 N 行,每行包含两个整数 ai,bi,表示一个区间的两个端点。
输出格式
输出一个整数,表示所需的点的最小数量。
数据范围
1≤N≤105,
−109≤ai≤bi≤109
输入样例:
3
-1 1
2 4
3 5
输出样例:
2
思路
关于第二点ans>=cnt的图
上文两个cnt的不同含义
第一个cnt表示每种可行方案中的点数,ans是最少点数的方案
第二个cnt表示ans是至少要cnt个点覆盖掉cnt个区间
AC代码
#include<iostream>
#include<cstring>
#include<algorithm>
#include<cstdio>
using namespace std;
const int N=100010;
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;//res表示当前选择的点的数量,ed表示上一个点的下标
//最开始因为我们一个点也没有选,所以赋成负无穷
for(int i=0;i<n;i++)//枚举所有区间
{
if(range[i].l>ed)//如果当前区间的左端点严格大于ed的话
{
res++;//选择一个新的点
ed=range[i].r;//当前选择点的下标更新成右端点
}
}
printf("%d\n",res);
return 0;
}