AcWing 907. 区间覆盖
原题链接
简单
作者:
ITNXD
,
2020-09-21 17:34:00
,
所有人可见
,
阅读 415
简单题解
参考代码:
#include <iostream>
#include <algorithm>
#include <cstring>
using namespace std;
const int N = 1e5 + 10;
int n, st, ed;
struct Range{
int l, r;
bool operator < (const Range w) const {
return l < w.l;
}
}range[N];
// 1. 按照区间左端点排序
// 2. 从前向后扫描所有能覆盖目标区间左端点start的区间中,选择右端点最大的区间,并更新目标区间的左端点为最大右端点
// 简单证明:对于res(最终答案:每个区间右端点不一定最大) 和 cnt(我们算法的答案)
// 对于res会发现他会被cnt的每个区间覆盖掉,可以证明最终res = cnt
int main(){
cin >> st >> ed >> n;
for(int i = 0; i < n; i++){
int l, r;
cin >> l >> r;
range[i] = {l, r};
}
sort(range, range + n);
int res = 0;
// sucess用来判断最后一部分能否完全覆盖,不可省略
bool sucess = false;
for(int i = 0; i < n;){
int j = i, r = -2e9;
// j = i 表示从第一个没有扫描的区间开始
// 将所有包含目标区间开始位置的区间的最大右端点找出来,其他不是最大的就是没用的区间
while(j < n && range[j].l <= st){
r = max(r, range[j].r);
j ++;
}
// 最大右端点都到不了区间开始则输出-1结束
if(r < st){
cout << -1 << endl;
return 0;
}
res ++;
// 当前最大右端点比目标区间都长,提前结束
if(r >= ed){
sucess = true;
break;
}
// 更新目标区间开始位置为当前最大右端点,扫描位置更新为j,即没有扫描过的第一个位置
st = r, i = j;
}
if(sucess) cout << res << endl;
else cout << -1 << endl;
return 0;
}