传送门
题面描述:
农民John的牧场上有一种世界上最美味的草,所以全世界的牛都要过来尝尝,但是John的牧场非常的小,牛又来的很多,因此他们需要排队品尝这种草。一旦牛开始吃草,它就会在离开之前花费她的全部时间(ti),在此期间,其他已到达的奶牛需要等待。如果当牧场再次可用时,多头奶牛在等待,那么具有最高资历的奶牛将被允许对草进行采样(输入数据时按照资历降序输入,就是越前面的牛资历越高,不管它的到达时间)。为此目的,一头牛到达时有另一头牛正在吃草,被认为是“等待”。同样地,如果许多奶牛都在完全相同的时间到达而没有奶牛正在吃东西,那么资历最高的奶牛就是下一个吃的。计算所有牛中可能需要等待的最长时间。
题目分析:
这题用优先队列做比较好,先把数据全部保存进结构体数组,然后按照:
- 到达顺序优先
- 资历优先
的顺序排好,注意优先队列是用来存放正在等待的牛的,所以要重载小于号,让优先队列的规则为资历越高(id越小)越先推出。按照排好后的顺序从1到n遍历每一头牛,对于每一头牛要对当前的时间time和队列是否为空进行判断:
- 当前时间大于等于当前牛到达的时间(牛不能一到就吃草,要放到队列里面进行比较)
- 当前时间小于当前牛到达的时间(理论上这只牛一到就能吃草)但是队列不为空(要先处理队列里面的牛),就要先处理队列中的牛,对当前时间和可能的最大等待时间进行更新
- 对于第2种情况,跳出while循环有两种可能,第一种是队列为空时跳出,说明当前牛到达时间大于当前时间,而这段时间是没有牛在吃草的,所以只需要更新当前时间为当前牛的到达时间+吃草时间。第二种是队列非空但当前牛到达时间小于当前时间跳出,就要继续把这只牛push进优先队列。
遍历完所有牛后就能找到最大时间。
代码:
#include<stdio.h>
#include<algorithm>
#include<iostream>
#include<string.h>
#include<queue>
#include<vector>
using namespace std;
int i,n;
struct COW{
int id;
long long a,t;
}cow[100005];
bool cmp(COW a,COW b){//sort规则,结构体也可以排序
if(a.a!=b.a) return a.a<b.a;
else return a.id<b.id;
}
bool operator < (COW a,COW b){// < 重载优先队列的规则,id越小的越先摊出
return a.id>b.id;
}
priority_queue<COW> q;//建立优先队列,规则为上面重载后的
int main(){
cin>>n;
for(i=1;i<=n;i++){
cow[i].id=i;
cin>>cow[i].a>>cow[i].t;
}
sort(cow+1,cow+1+n,cmp);
long long ans=0,time=0;
for(i=1;i<=n;i++){
if(cow[i].a<=time){
COW t;
t.id=cow[i].id,t.a=cow[i].a,t.t=cow[i].t;
q.push(t);
continue;//排序后的牛到达时间如果不比当前时间大,就一直放进队列,直到有空的时候从队列中按id取出牛吃草
}
while(cow[i].a>time&&!q.empty()){//出循环的情况有队列为空和非空两种
COW t=q.top();
q.pop();
ans=max(ans,time-t.a);
time+=t.t;
}
if(!q.empty()){//队列非空就得继续放进去直到有空才取出
COW t;
t.id=cow[i].id,t.a=cow[i].a,t.t=cow[i].t;
q.push(t);
continue;
}
time=cow[i].a+cow[i].t;//队列不为空,该牛到达时间比当前时间大,更新时间,该牛等待时间为0;
}
cout<<ans;
}