Convention II
题目描述
虽然在接机上耽误了挺长时间,Farmer John为吃草爱好牛们举行的大会至今为止都非常顺利。大会吸引了世界各地的奶牛。
然而大会的重头戏看起来却给Farmer John带来了一些新的安排上的困扰。他的农场上的一块非常小的牧草地出产一种据某些识货的奶牛说是世界上最美味的品种的草。因此,所有参会的N头奶牛(
1
≤
N
≤
1
0
5
1≤N≤10^5
1≤N≤105)都想要品尝一下这种草。由于这块牧草地小到仅能容纳一头奶牛,这很有可能会导致排起长龙。
Farmer John知道每头奶牛ii计划到达这块特殊的牧草地的时间ai,以及当轮到她时,她计划品尝这种草花费的时间ti。当奶牛ii开始吃草时,她会在离开前花费全部ti的时间,此时其他到达的奶牛需要排队等候。如果这块牧草地空出来的时候多头奶牛同时在等候,那么资历最深的奶牛将会是下一头品尝鲜草的奶牛。需要说明的是,恰好在另一头奶牛吃完草离开时到达的奶牛被认为是“在等待的”。类似地,如果当没有奶牛在吃草的时候有多头奶牛同时到达,那么资历最深的奶牛是下一头吃草的奶牛。
请帮助FJ计算所有奶牛中在队伍里等待的时间(ai到这头奶牛开始吃草之间的时间)的最大值。
输入描述:
输入的第一行包含N。以下N行按资历顺序给出了N头奶牛的信息(资历最深的奶牛排在最前面)。每行包含一头奶牛的ai和ti。所有的titi为不超过
1
0
4
10^4
104的正整数,所有的ai为不超过
1
0
9
10^9
109的正整数。
输出描述:
输出所有奶牛中的最长等待时间。
示例1
输入
5
25 3
105 30
20 50
10 17
100 10
输出
10
说明
在这个例子中,我们有5头奶牛(按输入中的顺序编号为1…5)。奶牛4最先到达(时间10),在她吃完之前(时间27)奶牛1和奶牛3都到达了。由于奶牛1拥有较深的资历,所以她先吃,从她到达开始共计等待了2个单位时间。她在时间30结束吃草,随后奶牛3开始吃草,从她到达开始共计等待了10单位时间。在一段没有奶牛吃草的时间过后,奶牛5到达,在她正在吃草的时间里奶牛2也到达了,在5个单位时间之后能够吃到草。相比于到达时间等待最久的奶牛是奶牛3。
题解: 详细逻辑见代码。
c++ AC 代码
#include <bits/stdc++.h>
using namespace std;
const int N = 1e5 + 5;
struct Cow
{
int s; // 抵达时间
int e; // 奶牛的吃草时长
int id; // 奶牛的资历
} a[N], b[N];
int n, spend, cnt, ans; // spend 代表累积的总时间,cnt 代表当前有几头牛吃过草了 ans 储存最长的等待时间
priority_queue<int, vector<int>, greater<int>> que; // 优先队列存当前需要等待吃草的牛,根据它们的资历排序(题目输入越靠前,资历越深,越先吃草(greater是小根堆))
bool cmp(const Cow &a, const Cow &b)
{
return a.s != b.s ? a.s < b.s : a.id < b.id;
}
int main()
{
scanf("%d", &n);
for (int i = 1; i <= n; i++)
{
scanf("%d%d", &a[i].s, &a[i].e);
a[i].id = i;
b[i] = a[i];
}
sort(a + 1, a + 1 + n, cmp); // 将a中的牛按照抵达的先后顺序进行排序 b 中代表的是牛的资历,排在越前面的牛的资历越深
que.push(a[1].id); // 最先来的牛开始吃草
spend = a[1].s;
cnt = 2; // 第一头牛已经在吃了,从第二头开始
while (!que.empty())
{
int now = que.top(); // 资历最深的牛先出队吃草。
que.pop();
ans = max(ans, spend - b[now].s); // spend - b[now].s ——> 前面的牛吃草的总时间减去当前牛抵达的时间,即当前牛在这段时间等待的时间
spend += b[now].e; // 当前牛吃完,把它的花费的时间加到spend中
while (cnt <= n && a[cnt].s <= spend) // 当前牛在吃完草前陆续有牛抵达草场,把这些陆续抵达且需要等待的牛加入到优先队列中
{ // 如果一头牛的抵达时间是在当前牛吃完草后,则不再理会,先处理完在该牛
// 吃草期间抵达草场的牛
que.push(a[cnt].id);
cnt++;
}
if (que.empty() && cnt <= n) // 如果等待期的牛都处理完了,而这时候又没有新的牛来
{ // 相当于这时候是草场的人休息的时间(打个比方而已),继而当再有牛来的时候
que.push(a[cnt].id); // 把它加入队列当中,并且将总时间直接拉到该牛抵达的时刻
spend = a[cnt].s;
cnt++;
}
}
printf("%d\n", ans);
//system("pause");
return 0;
}