区间覆盖(贪心)

题目:区间覆盖(贪心)

题意:

给定 N 个闭区间 [ai,bi] 以及一个线段区间 [s,t],请你选择尽量少的区间,将指定线段区间完全覆盖。

输出最少区间数,如果无法完全覆盖则输出 −1

输入格式

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

第二行包含整数 N,表示给定区间数。

接下来 N 行,每行包含两个整数 ai,bi,表示一个区间的两个端点。

输出格式

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

如果无解,则输出 −1

数据范围

1≤N≤1e5,
−1e9≤ai≤bi≤1e9,
−1e9≤s≤t≤1e9

输入样例:

1 5

3

-1 3

2 4

3 5

输出样例:

2

样例解释:

选择区间[-1, 3][3, 5],答案为2。

题目分析:贪心。

解题步骤:

  1. 将所有区间按左端点从小到大排序。
  2. 设当前要覆盖的线段的区间是[st, ed],从前往后枚举每个区间,选择左端点小于等于st且右端点最大的区间,更新要覆盖的线段的区间,此时答案 + 1;如果没有左端点小于等于st的区间,则说明无解,输出-1。

贪心策略证明:

  1. 设贪心得到的答案为cnt,本题的正确答案为ans。
  2. 由于本题的答案ans是所有方案的最小值,所有必有ans <= cnt。
  3. 设在正确答案中有选择左端点小于等于st,但右端点不是最大的区间。此时,我们将该区间替换成左端点小于等于st,右端点最大的区间是更优的(区间数相同,右端点更大)。故有cnt <= ans。
  4. 由于ans <= cntcnt <= ans,得cnt = ans。

AC代码:

#include<iostream>

#include<algorithm>

 

using namespace std;

const int N = 1e5 + 10;

struct st{

    int x, y;

    bool operator < (const st &X) const{

        return x < X.x;

    }

}a[N];

int n, st, ed;

 

void solve(){

    scanf("%d %d %d", &st, &ed, &n);

    for(int i = 1;i <= n;i++) scanf("%d %d", &a[i].x, &a[i].y);

    sort(a + 1, a + 1 + n);

    

    int res = 0, t = st;

    for(int i = 1;i <= n;i++){

        if(a[i].x <= st) t = max(t, a[i].y);

        else{

            res++;

            

            if(a[i].x > t){

                printf("-1\n");

                return;

            }

            else{

                st = max(a[i].x, t);

                t = max(t, a[i].y);

            }

        }

        

        if(t >= ed){

            res++;

            break;

        }

    }

    

    if(t < ed) res = -1;

    printf("%d\n", res);

}

 

int main(){

    solve();

    

    return 0;

}

时间复杂度:O(NlogN)。

空间复杂度:O(N)。

posted @   思丶君  阅读(96)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· AI技术革命,工作效率10个最佳AI工具
点击右上角即可分享
微信分享提示