一、算法思路
1、将所有区间按左端点从小到大排序。
2、从前往后依次枚举每个区间,在所有能覆盖(start)的区间中,选择右端点最大的区间,然后将(start)更新成右端点的最大值。
二、算法步骤
1、按左端点从小到大排序
2、遍历每个区间,利用双指针,从当前区间开始向后,找出覆盖start起点的区间,就是让区间尽可能的长
4、如果没有找到,表示出现了空隙,输出-1,退出
5、如果找到,多找出了一个区间,res++
6、如果已经完整覆盖,输出区间数量,结束
7、更新迭代起点
三、实现代码
#include <bits/stdc++.h>
using namespace std;
const int INF = 0x3f3f3f3f;
const int N = 100010;
struct Range {
int l, r;
} range[N];
//强制要求使用这种结构体的排序自定义函数方式
//按每个区间的左端点从小到大排序
bool cmp(const Range &a, const Range &b) {
return a.l < b.l;
}
int n; //n个区间
int st, ed; //开始端点,结束端点
int res; //选择的区间数
int main() {
//优化输入
ios::sync_with_stdio(false);
//输入
cin >> st >> ed >> n;
for (int i = 0; i < n; i++) {
int l, r;
cin >> l >> r;
range[i] = {l, r};
}
//1、按左端点从小到大排序
sort(range, range + n, cmp);
//2、遍历每个区间,注意这里的i没有++,因为可能一次跳过多个区间
for (int i = 0; i < n;) {
int j = i;
int r = -INF;//预求最大,先设最小
//3、双指针,从当前区间开始向后,找出覆盖start起点的区间,就是让区间尽可能的长
while (j < n && range[j].l <= st) {
r = max(r, range[j].r);//找出右端最长的那个区间
j++;
}
//4、如果没有找到,表示出现了空隙
if (r < st) {
printf("%d
", -1);
exit(0);
}
//5、如果找到,多找出了一个区间
res++;
//6、如果已经完整覆盖,输出
if (r >= ed) {
printf("%d
", res);
exit(0);
}
//7、更新迭代起点
st = r;
//指针跳跃
i = j;
}
//7、如果运行到这里,表示无法覆盖掉所有点
printf("-1");
return 0;
}