区间分组问题是将n个区间分成若干个组。
方法一般是
1.将区间的左端点从小到大排序
2.从前往后处理每个区间
[一般定义一个堆:
priority_queue<int,vector,greater> heap;]
if(可以放进当前组)直接放进当前组,并更新组的数据
else 建立一个新的组
给定N个闭区间[ai,bi ],请你将这些区间分成若干组,使得每组内部的区间两两之间(包括端点)没有交集,并使得组数尽可能小。
输出最小组数。 输入格式
第一行包含整数N,表示区间数。
接下来N行,每行包含两个整数ai,bi
,表示一个区间的两个端点。 输出格式
输出一个整数,表示最小组数。 数据范围
1≤N≤105 , −109≤ai≤bi≤109
输入样例:
3
-1 1
2 4
3 5输出样例:
2
此题可以看出要放进一个组的条件是
堆顶区间右端点<当前区间左端点
heap为空(-1,1)放进当前组1
1<2 可以放进当前组 (2,4)放进当前组1,并弹出堆顶
4>3 不能放进当前组 (3,5)放进新的组2
代码:
#include<queue>
#include<algorithm>
#include<iostream>
using namespace std;
const int N=1000010;
struct Range{
int l,r;
bool operator< (const Range& w)const{
return l<w.l;//自定义比较函数使得从小到大排序
}
}range[N];
int main()
{
int n;
cin>>n;
for(int i=0;i<n;i++)
{
int l,r;
cin>>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++)
{
if(heap.empty()||heap.top()>=range[i].l)
{
//不满足条件新增组
heap.push(range[i].r);
// cout<<heap.top()<<endl;
}
else{
// cout<<heap.top()<<endl;
//满足条件弹出堆顶,放入当前组
heap.pop();
heap.push(range[i].r);
}
}
cout<<heap.size();
return 0;
}
才学一题是不是感觉还没掌握呢?
那再来一题吧
有N头牛在畜栏中吃草。
每个畜栏在同一时间段只能提供给一头牛吃草,所以可能会需要多个畜栏。
给定N头牛和每头牛开始吃草的时间A以及结束吃草的时间B,每头牛在[A,B]这一时间段内都会一直吃草。
当两头牛的吃草区间存在交集时(包括端点),这两头牛不能被安排在同一个畜栏吃草。
求需要的最小畜栏数目和每头牛对应的畜栏方案。 输入格式
第1行:输入一个整数N。
第2…N+1行:第i+1行输入第i头牛的开始吃草时间A以及结束吃草时间B,数之间用空格隔开。 输出格式
第1行:输入一个整数,代表所需最小畜栏数。
第2…N+1行:第i+1行输入第i头牛被安排到的畜栏编号,编号是从1开始的 连续 整数,只要方案合法即可。 数据范围
1≤N≤50000 , 1≤A,B≤1000000
输入样例:
5
1 10
2 4
3 6
5 8
4 7输出样例:
4
1
2
3
2
4
这题和上题其实几乎是一个道理
还是堆顶区间右端点<当前区间左端点

heap为空(1,10)放进当前组1[橙色]
10>2 不能放进当前组 (2,4)放进新的组2[紫]
4>3 不能放进当前组 (3,6)放进新的组3[紫]
4<5 可以放进当前组 (5,8)放进当前组2[紫]并弹出堆顶
6>4 不能放当前组 (4,7)放进新的组4[粉]
故有四个组 排列为 1 2 3 2 4
废话少说上代码
#include<iostream>
#include<queue>
#include<algorithm>
using namespace std;
const int N=500010;
struct Range
{
int l,r,index;//当前是第几头牛
bool operator< (const Range &W)const{
return l<W.l;
}
}range[N];
struct cmp
{
template <typename T, typename U>
bool operator()(T const &left, U const &right)
{
// 左端点进行排序
if (left.first > right.first)
return true;
return false;
}
};
int res[N];//存放围栏结果
int main()
{
int n;
cin>>n;
for(int i=0;i<n;i++)
{
int l,r;
cin>>l>>r;
range[i]={l,r,i};
}
sort(range,range+n);
priority_queue<pair<int,int>,vector<pair<int, int>>,cmp> heap;
int min=1e7;
int res_count=0;
pair<int,int> p;
for(int i=0;i<n;i++)
{
p.first=range[i].r;
if(heap.empty()||heap.top().first>=range[i].l)//不满足条件建新围栏
{
//围栏总数++,记录当前围栏的是几号
res[range[i].index]=p.second=++res_count;
heap.push(p);
// cout<<heap.top().first<<" "<<range[i].l<<" ";
}
else//满足条件用旧围栏
{
//当前围栏号等于堆顶围栏号
p.second=res[range[i].index]=heap.top().second;
heap.pop();
heap.push(p);
}
// cout<<p.first<<" "<<res[range[i].index]<<endl;
}
cout<<res_count<<endl;
for(int i=0;i<n;i++)
{
cout<<res[i]<<endl;
}
return 0;
}