Convention II

16 篇文章 0 订阅
10 篇文章 0 订阅

传送门

题面描述:

农民John的牧场上有一种世界上最美味的草,所以全世界的牛都要过来尝尝,但是John的牧场非常的小,牛又来的很多,因此他们需要排队品尝这种草。一旦牛开始吃草,它就会在离开之前花费她的全部时间(ti),在此期间,其他已到达的奶牛需要等待。如果当牧场再次可用时,多头奶牛在等待,那么具有最高资历的奶牛将被允许对草进行采样(输入数据时按照资历降序输入,就是越前面的牛资历越高,不管它的到达时间)。为此目的,一头牛到达时有另一头牛正在吃草,被认为是“等待”。同样地,如果许多奶牛都在完全相同的时间到达而没有奶牛正在吃东西,那么资历最高的奶牛就是下一个吃的。计算所有牛中可能需要等待的最长时间。

题目分析:

这题用优先队列做比较好,先把数据全部保存进结构体数组,然后按照:

  1. 到达顺序优先
  2. 资历优先

的顺序排好,注意优先队列是用来存放正在等待的牛的,所以要重载小于号,让优先队列的规则为资历越高(id越小)越先推出。按照排好后的顺序从1到n遍历每一头牛,对于每一头牛要对当前的时间time和队列是否为空进行判断:

  1. 当前时间大于等于当前牛到达的时间(牛不能一到就吃草,要放到队列里面进行比较)
  2. 当前时间小于当前牛到达的时间(理论上这只牛一到就能吃草)但是队列不为空(要先处理队列里面的牛),就要先处理队列中的牛,对当前时间和可能的最大等待时间进行更新
  3. 对于第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;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Yjonben

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值