题解:AcWing 907 区间覆盖

【算法来源】

AcWing:907. 区间覆盖 - AcWing题库

【题目描述】

给定 \(N\) 个区间 \([a_i,b_i]\) 以及一个区间 \([s,t]\),请你选择尽量少的区间,将指定区间完全覆盖。

输出最少区间数,如果无法完全覆盖则输出 \(-1\)

【输入】

第一行包含两个整数 \(s\)\(t\),表示给定区间的两个端点。

第二行包含整数 \(M\),表示给定区间数。

接下来 \(N\) 行,每行包含两个整数 \(a_i,b_i\),表示一个区间的两个端点。

【输出】

输出一个整数,表示所需最少区间数。

如果无解,则输出 \(-1\)

【输入样例】

1 5
3
-1 3
2 4
3 5

【输出样例】

2

【算法标签】

《AcWing 907 区间覆盖》 #贪心#

【代码详解】

#include <bits/stdc++.h>
using namespace std;

const int N = 100005;  // 定义最大区间数量

int n;  // 区间数量

// 定义区间结构体
struct Range
{
    int l, r;  // 区间的左右端点

    // 重载小于运算符,用于排序
    bool operator< (const Range &W) const
    {
        return l < W.l;  // 按照区间的左端点升序排序
    }
}range[N];  // 定义区间数组

int main()
{
    int st, ed;  // 目标区间的左右端点
    cin >> st >> ed;  // 输入目标区间
    cin >> n;  // 输入区间数量

    // 输入每个区间的左右端点
    for (int i=0; i<n; i++)
    {
        int l, r;
        cin >> l >> r;
        range[i] = {l, r};  // 将区间存入数组
    }

    sort(range, range+n);  // 按照区间的左端点进行排序

    int res = 0;  // 记录选择的区间数量
    bool success = false;  // 标记是否成功覆盖目标区间

    // 遍历所有区间
    for (int i=0; i<n; i++)
    {
        int j = i, r = -2e9;  // j 用于遍历区间,r 记录当前能覆盖的最远右端点
        // 找到所有左端点小于等于 st 的区间,并选择右端点最大的区间
        while (j < n && range[j].l <= st)
        {
            r = max(r, range[j].r);  // 更新 r 为最大的右端点
            j++;
        }

        // 如果 r < st,说明无法覆盖 st,直接退出
        if (r < st)
        {
            res = -1;  // 无法覆盖,标记为失败
            break;
        }

        res++;  // 选择一个区间
        if (r >= ed)  // 如果当前区间已经覆盖了 ed,标记成功并退出
        {
            success = true;
            break;
        }

        st = r;  // 更新 st 为当前区间的右端点
        i = j - 1;  // 跳过已经处理过的区间
    }

    // 如果最终没有覆盖 ed,标记为失败
    if (!success) res = -1;

    cout << res << endl;  // 输出结果
    return 0;
}

【运行结果】

1 5
3
-1 3
2 4
3 5
2
posted @ 2026-02-27 08:47  团爸讲算法  阅读(3)  评论(0)    收藏  举报