给定 N N N个闭区间 [ a i , b i ] [a_i,b_i] [ai?,bi?],以及一个线段区间 [ s , t ] [s,t] [s,t],请你选择尽量少的区间,将指定线段区间完全覆盖。
输出最少区间数,如果无法完全覆盖则输出 ? 1 -1 ?1。
第一行包含两个整数 s s s和 t t t,表示给定线段区间的两个端点。
第二行包含整数 N N N,表示给定区间数。
接下来 N N N行,每行包含两个整数 a i , b i a_i,b_i ai?,bi?,表示一个区间的两个端点。
输出一个整数,表示所需最少区间数。
如果无解,则输出 ? 1 -1 ?1。
1 ≤ N ≤ 1 0 5 1≤N≤10^5 1≤N≤105, ? 1 0 9 ≤ a i ≤ b i ≤ 1 0 9 -10^9≤a_i≤b_i≤10^9 ?109≤ai?≤bi?≤109,
? 1 0 9 ≤ s ≤ t ≤ 1 0 9 -10^9≤s≤t≤10^9 ?109≤s≤t≤109
1 5
3
-1 3
2 4
3 5
2
从测试样例分析,要覆盖线段区间 [ 1 , 5 ] [1,5] [1,5],只需要 2 2 2个闭区间 [ ? 1 , 3 ] [-1,3] [?1,3]和 [ 3 , 5 ] [3,5] [3,5],如下图所示。
可以采用贪心的思想来解决这个问题:
总的时间复杂度为 O ( n + n l o g n ) O(n + nlogn) O(n+nlogn)
#include <iostream>
#include <algorithm>
using namespace std;
const int N = 1e5 + 10;
typedef pair<int, int> PII;
PII st[N];
int main()
{
int s, t, n, ans = 0, flag = 0;
cin >> s >> t >> n;
for(int i = 0; i < n; i ++) cin >> st[i].first >> st[i].second;
//排序
sort(st, st + n);
for(int i = 0; i < n; i ++)
{
//在所有能覆盖线段左端点s的区间中,选择右端点最大的区间
int j = i, R = -1e9;
while(j < n && st[j].first <= s) R = max(R, st[j ++].second);
//无法覆盖左端点s
if(R < s) break;
ans ++; //需要的区间个数增加1
s = R; //更新要覆盖的左端点
if(s >= t) //覆盖完成
{
flag = 1;
break;
}
i = j - 1; //继续从当前区间向后遍历
}
if(flag) cout << ans;
else cout << -1;
return 0;
}