题目链接:http://acm.csust.edu.cn/problem/4003
CSDN食用链接:https://blog.csdn.net/qq_43906000/article/details/107739654
Description
高铁上有(n)个人第(i)个人编号为(i)他在(s_i) 时刻想去泡泡面,他泡面所需时间为(t_i)
假设他们从座位到饮水机的时间可以忽略不计。不过只有一台饮水机,所以他们要排队泡面。
特别的,泡面可以分很多次泡完。比如你泡面需要(3min),可以先泡(1min),那么接下来你所需泡面的时间为(2min)。
泡面机服务策略:
首先先来的人可以优先泡面;对于同时到达的人,优先服务剩余所需泡面最短的人;对于剩余时间相同的人,则优先服务编号较小的人。
意思就是如果某时刻来了某个人(x)泡面所需时间比正在使用饮水机的人(y)剩余泡面所需时间要短,那么(x)可以暂时请走(y),自己先服务。
设(n)个人完成泡面时间为(e_i) 。请输出(n)个人的(e_i-s_i-t_i)之和,答案对1000000007取模。
(1leq nleq 1e5,1leq s_i,t_ileq 1e9)
Input
第一行一个整数(n)。
接下来nn行每行两个整数,表示(s_i,t_i)
Output
一行一个整数表示答案。
Sample Input 1
3
0 5
1 2
2 1
Sample Output 1
4
Sample Input 2
4
0 5
1 2
0 2
1 2
Sample Output 2
10
Hint
对于样例1:
(e1=8,e2=3,e3=4,sum_{i=1}^{n}e_i-s_i-t_i=8-0-5+3-1-2+4-2-1=4)
emmm,不清楚这道题的本质,比赛的时候一直贪心QAQ。。。
后来在想了挺久之后才发现好像就是个模拟。。。我们先按照来的时间和泡的时间进行一下双关键字排序。我们服务的既然是最短时间的人,那么我们可以用一个优先队列来维护当前每个人的剩余时间。那么可以模拟如下:
对于第一个人,它可以泡到第二个人来,或者直接泡完。如果它可以直接泡完的话,那么我们就直接将答案加上结束时间,否则的话我们就将第一个人的时间减去已经泡了的时间再丢到队列里面去。如此循环下去直到所有的人都跑完了。那么现在队列里面还有多少个人可以直接一个个取出来加就好了。其模拟代码如下:
int cnt=1;
ll ed=0;
priority_queue<ll,vector<ll>,greater<ll> >q;
q.push(person[1].ti);
ed=person[1].st;
ll ans=0;
while (!q.empty() || cnt<n) {
if (q.empty()) {q.push(person[++cnt].ti); ed=person[cnt].ti;}
ll u=q.top();
q.pop();
if (cnt<n) {
ll st=person[cnt+1].st;
if (st<ed+u) {
q.push(ed+u-st);
q.push(person[++cnt].ti);
ed=st;
}
else { ans=(ans+u)%mod; ed+=u;}
}
else { ans=(ans+u)%mod; ed+=u;}
}
最后我们只需要将答案减去所有人的开始时间和泡的时间就好了。
以下是AC代码:
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int mac=1e5+10;
const ll mod=1e9+7;
struct node
{
ll st,ti;
bool operator<(const node&a)const{
if (st!=a.st) return st<a.st;
if (ti!=a.ti) return ti<a.ti;
}
}person[mac];
int main()
{
int n;
scanf ("%d",&n);
for (int i=1; i<=n; i++){
int st,ti;
scanf ("%d%d",&st,&ti);
person[i]=node{st,ti};
}
sort(person+1,person+1+n);
int cnt=1;
ll ed=0;
priority_queue<ll,vector<ll>,greater<ll> >q;
q.push(person[1].ti);
ed=person[1].st;
ll ans=0;
while (!q.empty() || cnt<n){
if (q.empty()) {q.push(person[++cnt].ti); ed=person[cnt].st;}
ll u=q.top();
q.pop();
if (cnt<n) {
ll st=person[cnt+1].st;
if (st<ed+u){
q.push(ed+u-st);
q.push(person[++cnt].ti);
ed=st;
}
else {ans=(ans+ed+u)%mod; ed+=u;}
}
else {ans=(ans+ed+u)%mod; ed+=u;}
}
ll sum=0;
for (int i=1; i<=n; i++)
sum=(sum+person[i].st+person[i].ti)%mod;
ans=(ans-sum+mod)%mod;
printf("%lld
",ans);
return 0;
}