题目传送门

一、算法思路

1、将所有区间按左端点从小到大排序。
2、从前往后依次枚举每个区间,在所有能覆盖\(start\)的区间中,选择右端点最大的区间,然后将\(start\)更新成右端点的最大值。

AcWing 907. 区间覆盖

二、算法步骤

1、按左端点从小到大排序

2、遍历每个区间,利用双指针,从当前区间开始向后,找出覆盖start起点的区间,就是让区间尽可能的长

4、如果没有找到,表示出现了空隙,输出-1,退出

5、如果找到,多找出了一个区间,res++

6、如果已经完整覆盖,输出区间数量,结束

7、更新迭代起点

三、实现代码

#include <bits/stdc++.h>

using namespace std;
const int INF = 0x3f3f3f3f;
const int N = 100010;

struct Range {
    int l, r;
} range[N];

//强制要求使用这种结构体的排序自定义函数方式
//按每个区间的左端点从小到大排序
bool cmp(const Range &a, const Range &b) {
    return a.l < b.l;
}

int n;          //n个区间
int st, ed;     //开始端点,结束端点
int res;        //选择的区间数

int main() {
    //优化输入
    ios::sync_with_stdio(false);

    //输入
    cin >> st >> ed >> n;
    for (int i = 0; i < n; i++) {
        int l, r;
        cin >> l >> r;
        range[i] = {l, r};
    }
    //1、按左端点从小到大排序
    sort(range, range + n, cmp);

    //2、遍历每个区间,注意这里的i没有++,因为可能一次跳过多个区间
    for (int i = 0; i < n;) {
        int j = i;
        int r = -INF;//预求最大,先设最小

        //3、双指针,从当前区间开始向后,找出覆盖start起点的区间,就是让区间尽可能的长
        while (j < n && range[j].l <= st) {
            r = max(r, range[j].r);//找出右端最长的那个区间
            j++;
        }
        //4、如果没有找到,表示出现了空隙
        if (r < st) {
            printf("%d\n", -1);
            exit(0);
        }
        //5、如果找到,多找出了一个区间
        res++;

        //6、如果已经完整覆盖,输出
        if (r >= ed) {
            printf("%d\n", res);
            exit(0);
        }
        //7、更新迭代起点
        st = r;
        
        //指针跳跃
        i = j;
    }
    //7、如果运行到这里,表示无法覆盖掉所有点
    printf("-1");
    return 0;
}

相关文章:

  • 2021-08-15
  • 2022-12-23
  • 2022-12-23
  • 2022-12-23
  • 2022-12-23
  • 2022-12-23
  • 2021-09-17
  • 2022-02-27
猜你喜欢
  • 2022-12-23
  • 2022-12-23
  • 2021-10-31
  • 2022-12-23
  • 2022-12-23
  • 2022-12-23
  • 2021-08-31
相关资源
相似解决方案