区间覆盖
作者:互联网
C++
区间覆盖
/*
问题描述:
给定 N 个闭区间 [ai,bi] 以及一个线段区间 [s,t],请你选择尽量少的区间,将指定线段区间完全覆盖。
输出最少区间数,如果无法完全覆盖则输出 −1。
输入格式:
第一行包含两个整数 s 和 t,表示给定线段区间的两个端点。
第二行包含整数 N,表示给定区间数。
接下来 N 行,每行包含两个整数 ai,bi,表示一个区间的两个端点。
输出格式:
输出一个整数,表示所需最少区间数。
如果无解,则输出 −1。
数据范围:
1 ≤ N ≤ 105,
−10^9 ≤ ai ≤ bi ≤ 10^9,
−10^9 ≤ s ≤ t ≤ 10^9
解题思路:
问题是在于如何覆盖 [s, t] 区间,也就是不断寻找在覆盖 s 的前提下,尽可能的向右走。
然后更新 目标为 [max_right, t],不断寻找,直到大于等于 t,或者是无解。
尽可能的向右走,要求我们区间左端点排序好一些,因为右端点为第一关键字排序的话,寻找max_right 复杂度较高。
左端点为第一关键字排序,可以使用双指针算法很快求解出 max_right。
*/
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
const int N = 100010, INF = 0x3f3f3f3f;
typedef pair<int, int> PII;
PII segments[N];
int n;
int l, r;
bool cmp(const PII &t1, const PII &t2) {
return t1.first < t2.first;
}
int solution_one() {
// sort
sort(segments + 1, segments + n + 1, cmp);
int ret = 0;
int limit = l;
int max_right = -INF;
for (int i = 1; i <= n; i ++ ) {
// 寻找当前 limit 的最大区间覆盖
max_right = -INF;
int j;
for (j = i; j <= n; j ++ ) {
if (segments[j].first <= limit) {
max_right = max(max_right, segments[j].second);
} else {
break;
}
}
i = j - 1;
if (max_right == -INF) {
return -1;
} else {
ret += 1;
limit = max_right;
if (limit >= r) {
break;
}
}
}
if (limit >= r) {
return ret;
} else {
return -1;
}
}
int main()
{
// input
scanf("%d%d", &l, &r);
scanf("%d", &n);
for (int i = 1; i <= n; i ++ ) {
scanf("%d%d", &segments[i].first, &segments[i].second);
}
int res = solution_one();
printf("%d\n", res);
return 0;
}
标签:PII,right,覆盖,int,端点,区间,include 来源: https://www.cnblogs.com/lucky-light/p/16484687.html