区间覆盖(贪心)
题目:区间覆盖(贪心)
题意:
给定 N 个闭区间 [ai,bi] 以及一个线段区间 [s,t],请你选择尽量少的区间,将指定线段区间完全覆盖。
输出最少区间数,如果无法完全覆盖则输出 −1。
输入格式
第一行包含两个整数 s 和 t,表示给定线段区间的两个端点。
第二行包含整数 N,表示给定区间数。
接下来 N 行,每行包含两个整数 ai,bi,表示一个区间的两个端点。
输出格式
输出一个整数,表示所需最少区间数。
如果无解,则输出 −1。
数据范围
1≤N≤1e5,
−1e9≤ai≤bi≤1e9,
−1e9≤s≤t≤1e9
输入样例:
1 5
3
-1 3
2 4
3 5
输出样例:
2
样例解释:
选择区间[-1, 3]和[3, 5],答案为2。
题目分析:贪心。
解题步骤:
- 将所有区间按左端点从小到大排序。
- 设当前要覆盖的线段的区间是[st, ed],从前往后枚举每个区间,选择左端点小于等于st且右端点最大的区间,更新要覆盖的线段的区间,此时答案 + 1;如果没有左端点小于等于st的区间,则说明无解,输出-1。
贪心策略证明:
- 设贪心得到的答案为cnt,本题的正确答案为ans。
- 由于本题的答案ans是所有方案的最小值,所有必有ans <= cnt。
- 设在正确答案中有选择左端点小于等于st,但右端点不是最大的区间。此时,我们将该区间替换成左端点小于等于st,右端点最大的区间是更优的(区间数相同,右端点更大)。故有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 x < X.x;
}
}a[N];
int n, st, ed;
void solve(){
scanf("%d %d %d", &st, &ed, &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 = st;
for(int i = 1;i <= n;i++){
if(a[i].x <= st) t = max(t, a[i].y);
else{
res++;
if(a[i].x > t){
printf("-1\n");
return;
}
else{
st = max(a[i].x, t);
t = max(t, a[i].y);
}
}
if(t >= ed){
res++;
break;
}
}
if(t < ed) res = -1;
printf("%d\n", res);
}
int main(){
solve();
return 0;
}
时间复杂度:O(NlogN)。
空间复杂度:O(N)。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· AI技术革命,工作效率10个最佳AI工具