区间选点(贪心)
题目:区间选点(贪心)
题意:
给定 N 个闭区间 [ai,bi],要在数轴上选择尽量少的点,使得每个区间内至少包含一个选出的点。
输出选择的点的最小数量。
位于区间端点上的点也算作区间内。
输入格式
第一行包含整数 N,表示区间数。
接下来 N 行,每行包含两个整数 ai,bi,表示一个区间的两个端点。
输出格式
输出一个整数,表示所需的点的最小数量。
数据范围
1≤N≤1e5,
−1e9≤ai≤bi≤1e9
输入样例:
3
-1 1
2 4
3 5
输出样例:
2
样例解释:选择点1,4可以覆盖三个区间,答案为2。
题目分析:贪心。
解题步骤:
- 将所有区间按右端点从小到大排序。
- 从头到尾枚举每一个区间。
(1) 若该区间已有点被覆盖,则跳过。
(2) 若该区间没有点被覆盖,则选择该区间的右端点,此时答案 + 1。
贪心策略证明:
- 设贪心得出的答案是cnt,本题的正确答案是ans。
- 由于本题的答案ans是所有方案的最小值,所以必有ans <= cnt。
- 设在正确答案中有某些点不是某个区间的右端点,由于区间是按右端点从小到大排序的,所以选择右端点能够为后面的区间获得更多的包含该点的可能,所以将正确答案中不是某个区间的右端点的点替换成右端点是更优的,所以有cnt <= ans。
- 由于ans <= cnt且cnt <= ans,得cnt = ans。
AC代码:
#include<iostream>
#include<algorithm>
using namespace std;
const int N = 1e5 + 10;
struct st{
int x, y;
bool operator < (const st &X) const{
return y < X.y;
}
}a[N];
int n;
void solve(){
scanf("%d", &n);
for(int i = 1;i <= n;i++) scanf("%d %d", &a[i].x, &a[i].y);
sort(a + 1, a + 1 + n);
int res = 0, t = -2e9;
for(int i = 1;i <= n;i++){
if(a[i].x > t){
res++;
t = a[i].y;
}
}
printf("%d\n", res);
}
int main(){
solve();
return 0;
}
时间复杂度:O(nlogn)。
空间复杂度:O(n)。
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】博客园社区专享云产品让利特惠,阿里云新客6.5折上折
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 在鹅厂做java开发是什么体验
· 百万级群聊的设计实践
· WPF到Web的无缝过渡:英雄联盟客户端的OpenSilver迁移实战
· 永远不要相信用户的输入:从 SQL 注入攻防看输入验证的重要性
· 浏览器原生「磁吸」效果!Anchor Positioning 锚点定位神器解析