
思路:
用两个优先队列模拟就好了
#pragma GCC optimize(2)
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <iostream>
#include <map>
#include <unordered_map>
#include <vector>
#include <queue>
using namespace std;
typedef unsigned long long ull;
typedef long long ll;
const int maxn = 2e5 + 7;
const int mod = 1e9 + 7;
ll E[maxn],S[maxn],T[maxn];
int n;
struct Node1 { //按到来的时间和剩余时间和编号排序
int id;
ll tim,res;
bool operator < (const Node1&rhs) const {
if(tim != rhs.tim) {
return tim > rhs.tim;
}
if(res != rhs.res) {
return res > rhs.res;
}
if(id != rhs.id) {
return id > rhs.id;
}
return true;
}
};
struct Node2 { //按剩余时间和编号排序
int id;
ll tim,res;
bool operator < (const Node2&rhs) const {
if(res != rhs.res) {
return res > rhs.res;
}
if(id != rhs.id) {
return id > rhs.id;
}
return true;
}
};
priority_queue<Node1>q; //到来的时间优先
priority_queue<Node2>p; //剩余的时间优先
int main() {
scanf("%d",&n);
for(int i = 1;i <= n;i++) {
scanf("%lld%lld",&S[i],&T[i]);
q.push({i,S[i],T[i]});
}
ll tim = 0;//泡面花了多少时间
ll pre = 0;
while(!q.empty()) {
Node1 now = q.top();q.pop();
ll num = now.tim - pre; //两次间隔的时间
if(!p.empty()) {
while(!p.empty() && num >= p.top().res) {
E[p.top().id] += (p.top().res + tim) % mod;
tim += p.top().res;
num -= p.top().res;
p.pop();
}
tim += num;
if(num && !p.empty()) {
Node2 tp = p.top();p.pop();
tp.res -= num;
p.push(tp);
}
} else {
tim += num;
}
pre = now.tim;
p.push(Node2{now.id,now.tim,now.res});
while(!q.empty() && q.top().tim == now.tim) {
now = q.top();q.pop();
p.push(Node2{now.id,now.tim,now.res});
}
}
while(!p.empty()) {
Node2 now = p.top();p.pop();
E[now.id] = (now.res + tim) % mod;
tim += now.res;
}
ll ans = 0;
for(int i = 1;i <= n;i++) {
// printf("FUCK %lld\n",E[i]);
ans += E[i] - S[i] - T[i];
ans %= mod;
}
ans = ((ans % mod) + mod) % mod;
printf("%lld\n",ans);
return 0;
}
1036

被折叠的 条评论
为什么被折叠?



