给定N个闭区间 [ a i , b i ] [a_i, b_i] [ai,bi]以及一个线段 [ s , t ] [s,t] [s,t],选择尽量少的区间,将线段完全覆盖。
第一行输入整数s和t,代表线段两个端点
第二行输入整数N,表示区间数
接下来N行输入整数 a i , b i a_i, b_i ai,bi,表示区间两个端点
输出一个整数,表示最少区间数
如果无解则输出-1
数据范围:
1 ≤ N ≤ 1 0 5 1 \leq N \leq 10^5 1≤N≤105
− 1 0 9 ≤ a i ≤ b i ≤ 1 0 9 -10^9 \leq a_i \leq b_i \leq 10^9 −109≤ai≤bi≤109
− 1 0 9 ≤ s ≤ t ≤ 1 0 9 -10^9 \leq s \leq t \leq 10^9 −109≤s≤t≤109
将区间按左端点从小到大排序,依次枚举每个区间。
设算法得到的区间的个数是A,最优解得到区间的个数是B
A = B A = B A=B:
假设算法得到的区间如下: [ a 1 l , a 1 r ] , [ a 2 l , a 2 r ] , . . . , [ a m l , a m r ] [a_{1l}, a_{1r}], [a_{2l}, a_{2r}], ..., [a_{ml}, a_{mr}] [a1l,a1r],[a2l,a2r],...,[aml,amr]
假设最优解的区间如下: [ b 1 l , b 1 r ] , [ b 2 l , b 2 r ] , . . . , [ b m l , b m r ] [b_{1l}, b_{1r}], [b_{2l}, b_{2r}], ..., [b_{ml}, b_{mr}] [b1l,b1r],[b2l,b2r],...,[bml,bmr]
上面的区间按左端点从小到大排序,比较第一个不一样的区间,不妨设 [ a 2 l , a 2 r ] [a_{2l}, a_{2r}] [a2l,a2r]和 [ b 2 l , b 2 r ] [b_{2l}, b_{2r}] [b2l,b2r],那么一定有 a 2 r > b 2 r a_{2r}>b_{2r} a2r>b2r,因为算法选择的是右端点最靠右的区间。
因为最优解是合法的,所以有 b 3 l < b 2 r b_{3l}
按照上述操作,拿A的区间依次替换B的区间,可以得到另一种最优解。
题目链接
注意这题是考虑点覆盖而不是线段覆盖,例如[1, 3][4, 5]可以覆盖[1, 5],因此判断条件是range[j].l <= last + 1
,并且r <= last
时退出。
如果是线段覆盖则要改成range[j].l <= last
,并且r < last
时退出
#include
#include
using namespace std;
const int N = 25005;
struct Range {
int l, r;
bool operator< (const Range &W)const {
return l < W.l;
}
}range[N];
int n, t;
int main() {
scanf("%d%d", &n, &t);
int st = 1, ed = t;
//scanf("%d%d", &st, &ed);
for (int i = 0; i < n; i ++ ) {
scanf("%d%d", &range[i].l, &range[i].r);
}
sort(range, range + n);
int ans = 0, last = st - 1;
bool flag = false;
for (int i = 0; i < n; i ++ ) {
int j = i, r = 0;
while (j < n && range[j].l <= last + 1) {
r = max(r, range[j].r);
j ++ ;
}
if (r <= last) {
flag = false;
break;
}
ans ++ ;
if (r >= ed) {
flag = true;
break;
}
last = r;
i = j - 1;
}
if (!flag) printf("-1");
else printf("%d", ans);
return 0;
}