给定N个闭区间[ai,bi],请你将这些区间分成若干组,使得每组内部的区间两两之间(包括端点)没有交集,并使得组数尽可能小。
输出最小组数。
输入格式
第一行包含整数N,表示区间数。
接下来N行,每行包含两个整数ai,biai,bi,表示一个区间的两个端点。
输出格式
输出一个整数,表示最小组数。
数据范围
1≤N≤105
−109 ≤ ai ≤ bi ≤ 109
输入样例:
3
-1 1
2 4
3 5
输出样例:
2
题目分析:
这是一道区间问题,所以我们首先要考虑排序准则。
这道题是按照区间的左端点进行排序,并且要记录下每个组的最右端点,并且每次拿出最右端点最小的组来进行比较。
如果某个待处理区间的左端点小于该最小右端点(说明有重合),那么就要开辟一个新的组来存这个区间。否则将区间放入当前组中并更新最右端点。
因为每次要从所有组中取出右端点最小的组进行操作,所以我们可以用小根堆来存储各个组的有端点。
代码如下:
#include <iostream>
#include <cstdio>
#include <cmath>
#include <string>
#include <cstring>
#include <queue>
#include <vector>
#include <algorithm>
#include <iomanip>
#define LL long long
using namespace std;
const int N=1e5+5;
struct Node{
int l,r;
bool operator< (const Node &a) const//定义排序准则
{
return l<a.l;
}
}a[N];
int main()
{
int n;
cin>>n;
for(int i=0;i<n;i++)
cin>>a[i].l>>a[i].r;
sort(a,a+n); //按左端点进行排序
priority_queue<int,vector<int>,greater<int> >heap; //定义小根堆
heap.push(a[0].r); //将第一个区间做为第一组
for(int i=1;i<n;i++)
{
int t=heap.top(); //取出最小右端点
heap.pop();
if(t<a[i].l) t=a[i].r; //如果该区间左端点大于该组的右端点
else{ //则跟新组右端点
heap.push(a[i].r); //否则新建一个组
}
heap.push(t); //将原组右端点重新放回去
}
cout<<heap.size()<<endl; //堆中元素数量即为组数
return 0;
}