区间问题(贪心)(二)

简介: AcWing 906. 区间分组

AcWing 906. 区间分组

本题链接:AcWing 906. 区间分组

本博客给出本题截图:


image.png

本题分析

按照左端点从小到大进行排序,如果存在本区间的右端点大于等于下一区间的左端点的话,意思就是两个区间有交集,那么就让答案 + 1,这里,我们用堆来模拟这个过程,堆(优先队列)(STL)见博客:(先鸽),手写堆见博客:(先鸽),我们堆中的元素存的是区间的右端点,这里我们用小根堆,即堆顶元素是右端点的最小值,如果堆为空或者堆顶元素要大于等于下一个区间的左端点,那么就要开一个新的组,把该区间的右端点放入堆中,反之即堆顶元素要小于下一个区间的左端点,那么就意味着,堆顶元素可以和该区间放入一个组中,因为我们要存储每一个组中的右端点的最大值作为该组的右端点,且堆顶元素小于下一区间的左端点,即堆顶元素小于下一区间的右端点,我们要存最大右端点,且这俩区间为一组,就弹出堆顶元素,然后把下一区间的右端点加入堆中.


AC代码

#include <cstdio>
#include <algorithm>
#include <queue>
using namespace std;
const int N = 100010;
struct St
{
    int l, r;
    bool operator < (const St w) const
    {
        return l < w.l;
    }
}st[N];
int main()
{
    int n;
    scanf("%d", &n);
    for (int i = 0; i < n; i ++ )
    {
        int l, r;
        scanf("%d%d", &l, &r);
        st[i] = {l, r};
    }
    sort(st, st + n);
    priority_queue <int, vector<int>, greater<int>> heap;
    for (int i = 0; i < n; i ++ )
    {
        auto t = st[i];
        if (heap.empty() || heap.top() >= t.l) heap.push(t.r);
        else
        {
            heap.pop();
            heap.push(t.r);
        }
    }
    printf("%d", heap.size());
    return 0;
}

AcWing 907. 区间覆盖

本题链接:AcWing 907. 区间覆盖

本博客给出本题截图:

image.png

本题分析

先按照左端点从小到大进行排序。如何获得本题的最优解:st代表还未更新定线段区间的左端点,我们的核心目的就是在左端点i都小于st的情况下,选择右端点最大的区间

AC代码

#include <cstdio>
#include <algorithm>
using namespace std;
const int N = 100010;
struct Range
{
    int l, r;
    bool operator < (const Range w) const
    {
        return l < w.l;
    }
}range[N];
int main()
{
    int st, ed;
    scanf("%d%d", &st, &ed);
    int n;
    scanf("%d", &n);
    for (int i = 0; i < n; i ++ )
    {
        int l, r;
        scanf("%d%d", &l, &r);
        range[i] = {l, r};
    }
    sort(range, range + n);
    bool success = false;
    int res = 0;
    for (int i = 0; i < n; i ++ )
    {
        int j = i, r = -1e9;
        while (j < n && range[j].l <= st)
        {
            r = max(r, range[j].r);
            j ++;
        }
        res ++;
        if (r < st) break;
        if (r >= ed)
        {
            success = true;
            break;
        }
        st = r;
        i = j - 1;
    }
    if (!success) printf("-1");
    else printf("%d", res);
    return 0;
}

三、时间复杂度

关于贪心——区间选点的时间复杂度以及证明,后续会给出详细的说明以及证明过程,目前先鸽了。


目录
相关文章
|
9月前
|
算法 测试技术 C++
C++二分算法习题:判断是否是完全平方数[容易]和排列箱子[容易]
C++二分算法习题:判断是否是完全平方数[容易]和排列箱子[容易]
|
2月前
|
测试技术
【动态规划】【组合数学】1866. 恰有 K 根木棍可以看到的排列数目
【动态规划】【组合数学】1866. 恰有 K 根木棍可以看到的排列数目
|
2月前
|
C++
2589. 完成所有任务的最少时间(区间取点——贪心or线段树)
2589. 完成所有任务的最少时间(区间取点——贪心or线段树)
|
2月前
代码随想录Day30 贪心05 LeetCode T435无重叠区间 T763划分字母区间 T56 合并区间
代码随想录Day30 贪心05 LeetCode T435无重叠区间 T763划分字母区间 T56 合并区间
38 0
|
2月前
|
存储 算法 索引
算法题解-汇总区间
算法题解-汇总区间
|
12月前
|
人工智能 算法 BI
贪心算法——区间选点与最大不相交区间数
贪心算法——区间选点与最大不相交区间数
50 0
leetcode-每日一题1403. 非递增顺序的最小子序列(贪心)
时间复杂度:O(n logn) 其中n时数组长度,对数组进行排序需要O(n logn)的时间,对数组进行遍历需要O(n)的时间
81 0
leetcode-每日一题1403. 非递增顺序的最小子序列(贪心)
代码随想录刷题|LeetCode 435. 无重叠区间 763.划分字母区间 56. 合并区间
代码随想录刷题|LeetCode 435. 无重叠区间 763.划分字母区间 56. 合并区间
代码随想录刷题|LeetCode 435. 无重叠区间 763.划分字母区间 56. 合并区间
|
存储 算法
LeetCode 435. 无重叠区间(贪心算法,动态规划)
LeetCode 435. 无重叠区间(贪心算法,动态规划)
104 0
LeetCode 435. 无重叠区间(贪心算法,动态规划)

热门文章

最新文章