贪心之区间分组
题目链接:906. 区间分组 - AcWing题库
题目描述:给出几个区间,要求给区间分组,每一组内区间不能重合,求分的的最小组数
算法步骤
1)将所有的区间按左端点从小到大排序
2)从前往后处理每个区间
判断能否将其放入到某个现有的组中 l[i] > Max_r// l[i]是当前区间的左端点,Max_r是组的最右边的右端点
a.如果不存在这样的组,则开新组,然后放入
b.如果存在,则放入,更新Max_r
注意:用小根堆实现,小根堆能动态排序
问题:为什么每次和堆的头部,也就是所有组最大右端点的最小进行比较
因为新区间左端点如果比最小值还要小的话那肯定和其他的也重合了,就要开新组
那为什么比最小值大的话就一定可以加入组呢,就是可以啊,一定可以加入最大右端点最小的那个组
代码实现
#include <iostream>
#include <algorithm>
#include <queue>
using namespace std;
const int N = 1e5+10;
int n;
struct Ange{
int l,r;
}ange[N];
bool cmp(Ange a,Ange b)
{
return a.l < b.l;
}
int main()
{
cin >> n;
for(int i = 0; i < n; i ++ )
{
int a,b;
cin >> a >> b;
ange[i] = {a,b};
}
//按照左端点进行排序
sort(ange,ange + n,cmp);
//小根堆写法,堆中存储每个组的最大右端点,堆的大小即为组数
priority_queue<int,vector<int>,greater<int>> heap;
//从前往后处理每个区间
for(int i = 0; i < n; i ++ )
{
//如果堆为空或者说新区间和某一组有重合,就开新组,然后放入
if(heap.empty() || heap.top() >= ange[i].l)
heap.push(ange[i].r);
//如果新区间没有和任何一组重合,那就放入一组当中,并更新最小右端点
else
{
heap.pop();
heap.push(ange[i].r);
}
//我疑惑的点在于,为什么这两种操作都将右端点加入堆,那堆的组数是如何定义的呢,
//发现 第一种情况下没有弹出堆顶元素,说明开了新组,
//第二种情况弹出堆顶,说明没开新组
//
}
cout << heap.size() << endl;
return 0;
}