AcWing 906. 区间分组

题目描述

给定 N 个闭区间 [ai,bi],请你将这些区间分成若干组,使得每组内部的区间两两之间(包括端点)没有交集,并使得组数尽可能小。

输出最小组数。

输入格式

第一行包含整数 N,表示区间数。

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

输出格式

输出一个整数,表示最小组数。

数据范围

\(1≤N≤10^5\)
\(−10^9≤ai≤bi≤10^9\)

输入样例:

3
-1 1
2 4
3 5

输出样例:

2

贪心算法求解

分析

首先所有区间按照左端点排序

维护一个小根堆h,堆里存的是每组区间的最右端点

然后遍历所有区间,设当前的区间左端点是l

  • l <= h.top():就是说所有组的右端点都大于当前区间的左端点,由于一开始已经按照左端点排序所以所有组的左端点都小于当前组的左端点;所以当前区间一定与所有组内的区间相交,需要新开一个组来存本区间
  • 否则,当l > h.top()那么就可以将本区间存入到第一组中,并更新第一组的最有端点为本区间的右端点(因为此时l > h.topr肯定也大于h.top()

代码

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<queue>
using namespace std;
typedef pair<int, int> PII;
const int N = 100010;

PII s[N];
int n;

int main()
{
    scanf("%d", &n);
    for(int i = 0; i < n; i++) 
    {
        PII t;
        scanf("%d%d", &t.first, &t.second);
        s[i] = t;
    }
    sort(s, s+n); // 按左端点从小到大排序
    
    // 小根堆,只支持int
    priority_queue<int, vector<int>, greater<int>> h; // 用来存每组区间最右端点
    
    for(int i = 0; i < n; i++)
    {
        int l = s[i].first, r = s[i].second;
        
        if(h.empty() || h.top() >= l) // 如果堆为空,或者所有组中右端点最小值 都大于当前区间左端点,就要新开一个组放该区间
        {
            h.push(r);
        }
        else // 否则放入右端点最小的那个区间
        {
            h.pop();
            h.push(r);
        }
    }
    cout << h.size() << endl;
    return 0;
}

时间复杂度

新的思路

分析

看了一下,貌似是求最大”区间厚度的问题。
大家可以把这个问题想象成活动安排问题

有若干个活动,第i个活动开始时间和结束时间是\([Si,fi]\),同一个教室安排的活动之间不能交叠,求要安排所有活动,少需要几个教室?

有时间冲突的活动不能安排在同一间教室,与该问题的限制条件相同,即最小需要的教室个数即为该题答案。

我们可以把所有开始时间和结束时间排序,遇到开始时间就把需要的教室加1,遇到结束时间就把需要的教室减1,在一系列需要的教室个数变化的过程中,峰值就是多同时进行的活动数,也是我们至少需要的教室数。

C++ 代码

#include <iostream>
#include <algorithm>

using namespace std;

const int N = 100100;

int n;
int b[2 * N], idx;

int main()
{
    scanf ("%d", &n);
    for(int i = 0; i < n; i ++)
    {
        int l, r;
        scanf("%d %d", &l, &r);
        b[idx ++] = l * 2;//标记左端点为偶数。
        b[idx ++] = r * 2 + 1;// 标记右端点为奇数。
    }

    sort(b, b + idx);

    int res = 1, t = 0;
    for(int i = 0; i < idx; i ++)
    {
        if(b[i] % 2 == 0) t ++;
        else t --;
        res = max(res, t);
    }
    printf ("%d\n", res);
    return 0;
}


作者:未来i
链接:https://www.acwing.com/solution/content/8902/
来源:AcWing
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

代码

时间复杂度

参考文章

https://www.acwing.com/activity/content/code/content/65079/

https://www.acwing.com/solution/content/8902/

https://www.acwing.com/solution/content/79347/

posted @ 2022-02-27 15:50  VanHope  阅读(62)  评论(0编辑  收藏  举报