题目描述
有N头牛在畜栏中吃草。
每个畜栏在同一时间段只能提供给一头牛吃草,所以可能会需要多个畜栏。
给定N头牛和每头牛开始吃草的时间A以及结束吃草的时间B,每头牛在[A,B]这一时间段内都会一直吃草。
求需要的最小畜栏数目和每头牛对应的畜栏方案。
输入格式
第1行:输入一个整数N。
第2..N+1行:第i+1行输入第i头牛的开始吃草时间A以及结束吃草时间B,数之间用空格隔开。
输出格式
第1行:输入一个整数,代表所需最小畜栏数。
第2..N+1行:第i+1行输入第i头牛被安排到的畜栏编号。
数据范围
$1≤N≤50000$
$1≤A,B≤1000000$
样例
输入样例:
5
1 10
2 4
3 6
5 8
4 7
输出样例:
4
1
2
3
2
4
贪心+小根堆
这道题目的重点在第二问,因此我们可以选择这样的做法,首先排序这群奶牛,然后我们可以以时间轴为基础,每一头奶牛为枚举点即可,具体看代码实现.
C++ 代码
#include <bits/stdc++.h>
using namespace std;
const int N=50100;
struct node
{
int l;
int r;
int x;
bool operator <(const node &a)const
{
if(r==a.r)
return l>a.l;
return r>a.r;
}
} a[N];
priority_queue<node> p;
int n,m,i,j,as[N];
int cmp(node a,node b)
{
if (a.l==b.l)
return a.r<b.r;
return a.l<b.l;
}
int main()
{
ios::sync_with_stdio(false);
cin>>n;
for (i=1;i<=n;i++)
cin>>a[i].l>>a[i].r,a[i].x=i;
sort(a+1,a+1+n,cmp);
int ans=0;
for (i=1;i<=n;i++)
{
if (!p.empty() && p.top().r<a[i].l) //就是我们这头牛开吃的时间在堆顶这头牛吃完后.
{
as[a[i].x]=as[p.top().x];
p.pop();
}
else
{
ans++;
as[a[i].x]=ans;
}
p.push(a[i]);
}
cout<<ans<<endl;
for (i=1;i<=n;i++)
cout<<as[i]<<endl;
return 0;
}
请问bool operator <(const node &a)const
{
if(r==a.r)
return l>a.l;
return r>a.r;
}
排序为什么是r与a.r比骄,而不是像下文中的cmp是a.r与b.r比较???
这个排序是按照什么原则排的???
恳求帮助!!!
这是运算符重载
秀!
小根堆和大根堆都是什么时候用的
如何用前缀和,差分来求最小牛畜栏呢
我突然想起来了,这个算法似乎不可以了.QwQ,莫名尴尬.
以前的题解,都写得不怎么好,只有一两句话,后来我题解换了一套模板写,题解才略有所长.
大佬谦虚了
if (!p.empty() && p.top().r<a[i].l)
{
as[a[i].x]=as[p.top().x];
p.pop();
}
大佬,为什么要pop掉呢
因为堆顶的这头牛他吃完了,现在我们当前的牛要开吃了.所以当然要pop掉堆顶.
嗷嗷,明白了,谢谢
不谢,加油!
测试一下这组数据,应有的输出是:
只要方案合法即可。题目中有这句话.
还是感谢提供数据.
大佬 ,请问 strcut 里的那个
bool operator <(const node &a)const
{
if(r==a.r)
return l>a.l;
return r>a.r;
}
的作用是什么,为什么不打这个编译过不了?
这个就是自定义排序cmp函数,只不过内嵌到里面去了,因为priority_queue默认最小排序,是和结构体排序冲突的.你需要内嵌cmp函数在结构体中,达到重构排序比较函数.
好的,谢谢。