区间问题(贪心)(二)

简介: 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;
}

三、时间复杂度

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


目录
相关文章
|
8月前
leetcode-435:无重叠区间
leetcode-435:无重叠区间
38 0
|
5月前
|
算法 Java
LeetCode初级算法题:子数组最大平均数+二叉树的最小深度+最长连续递增序列+柠檬水找零
LeetCode初级算法题:子数组最大平均数+二叉树的最小深度+最长连续递增序列+柠檬水找零
47 0
|
8月前
DAY-4 | 力扣 - 求自身以外数组的乘积:区间划分,左右累乘,巧求乘积
该文档是关于LeetCode上的一道题目“Product of Array Except Self”的题解。提供了两种解题方法,一是暴力破解,即计算所有数的乘积后再逐个除以当前元素;二是左右累乘法,通过两次遍历数组分别计算左侧和右侧元素的乘积,避免了除法操作。其中,左右累乘法更优,代码实现中展示了这种方法。
56 1
|
8月前
|
C++
2589. 完成所有任务的最少时间(区间取点——贪心or线段树)
2589. 完成所有任务的最少时间(区间取点——贪心or线段树)
|
8月前
|
人工智能 算法
前缀和算法题(区间次方和、小蓝平衡和、大石头的搬运工、最大数组和)
前缀和算法题(区间次方和、小蓝平衡和、大石头的搬运工、最大数组和)
|
8月前
代码随想录Day30 贪心05 LeetCode T435无重叠区间 T763划分字母区间 T56 合并区间
代码随想录Day30 贪心05 LeetCode T435无重叠区间 T763划分字母区间 T56 合并区间
56 0
|
人工智能 算法 BI
贪心算法——区间选点与最大不相交区间数
贪心算法——区间选点与最大不相交区间数
85 0
区间选点(贪心)
这个题,虽然没有写过,但是我盲猜这个题肯定很经典
116 0
|
C++
(排列,选择类dp)(数论同余定理,同余运算)(以背包为母题)1214. 波动数列
(排列,选择类dp)(数论同余定理,同余运算)(以背包为母题)1214. 波动数列
102 0
leetcode-每日一题1403. 非递增顺序的最小子序列(贪心)
时间复杂度:O(n logn) 其中n时数组长度,对数组进行排序需要O(n logn)的时间,对数组进行遍历需要O(n)的时间
104 0
leetcode-每日一题1403. 非递增顺序的最小子序列(贪心)