其他分享
首页 > 其他分享> > 区间覆盖

区间覆盖

作者:互联网

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