[AcWing 906] 区间分组

image

差分 + 贪心


点击查看代码
#include<bits/stdc++.h>

using namespace std;

typedef long long LL;

const int N = 1e5 + 10;

int n;

void solve()
{
    cin >> n;
    vector<pair<int,int>> s;
    for (int i = 0; i < n; i ++) {
        int a, b;
        cin >> a >> b;
        s.push_back({a, 1});
        s.push_back({b + 1, -1});
    }
    sort(s.begin(), s.end());
    int res = 0, sum = 0;
    for (auto [x, c] : s) {
        sum += c;
        res = max(res, sum);
    }
    cout << res << endl;
}

signed main()
{
    ios::sync_with_stdio(false);
    cin.tie(nullptr);
    cout.tie(nullptr);

    solve();

    return 0;
}

  1. 利用差分,找到被最多区间覆盖的一段,这段就是所需的最小区间数目

小根堆 + 贪心


点击查看代码
#include<iostream>
#include<algorithm>
#include<queue>

using namespace std;
const int N = 1e5 + 10;
int n;

struct Range {
    int l, r;
    bool operator < (const Range &W) const {
        return l < W.l;
    }
}range[N];

int main()
{
    cin >> n;
    for (int i = 0; i < n; i ++) {
        int l, r;
        scanf("%d %d", &l, &r);
        range[i] = {l, r};
    }
    sort(range, range + n);
    priority_queue<int, vector<int>, greater<int>> heap;
    for (int i = 0; i < n; i ++) {
        auto r = range[i];
        if (heap.empty() || heap.top() >= r.l)  heap.push(r.r);
        else {
            heap.pop();
            heap.push(r.r);
        }
    }
    cout << heap.size() << endl;
    return 0;
}

  1. 算法思想
    ① 将所有区间按左端点从小到大排序
    ② 从前往后处理每个区间
    判断是否将其放到放到某个现有的组中 L[i]max(r)
    如果不存在这样的组,则开新组,然后再将其放进去
    如果存在这样的组,将其放进去,并更新当前组的 max(r)
    (使用小根堆维护右端点最小值,每次只需判断当前区间左端点和小根堆最小值的关系,更新时,把小根堆最小值进行更新)
  2. 算法的最优性解释
    设最优解是 ans ,一种可行解是 cnt
    ① 最优解要保证组数最小,即 anscnt
    ② 根据算法思路,在选第 cnt 个组时,前 cnt1 个组的区间都与第 cnt 个组的区间有交集,也就是说,至少需要 cnt 个组,才能保证区间没有交集,anscnt
    综上, ans=cnt ,最优性得证
posted @   wKingYu  阅读(37)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 分享4款.NET开源、免费、实用的商城系统
· 全程不用写代码,我用AI程序员写了一个飞机大战
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了
· 上周热点回顾(2.24-3.2)
欢迎阅读『[AcWing 906] 区间分组』
点击右上角即可分享
微信分享提示