题意
按时间顺序给出在某地借还车记录。
+ t k
表示在时刻 t ,该地新增 k 辆自行车- t k
表示在时刻 t ,k 个人来借车。
每个人借车必定按照来的先后顺序获得车辆,等待时间为 获得车辆的时刻 - 准备借车的时刻
。
对于 q 组询问,每组询问求在初始 0 时刻该地有 b 辆车的前提下,所有借车人的总等待时间?
解题思路
扫描线问题。
x 轴表示时间,y 轴表示当前等待的人数,则对于每个初始时刻有的车辆 b,重做一条 y = b
的线与区域所围成的几何图形的面积即为总的等待时间。
代码
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
#include<fstream>
using namespace std;
const int N = 1e5 + 10;
char op;
int n, q, t[N], k[N];
struct Node {
int wait, len;
} p[N];
bool operator<(Node a, Node b) { return a.wait > b.wait; }
struct Query {
int q, idx; long long ans;
} qry[N];
bool cmp(Query a, Query b) { return a.q > b.q; }
bool cmp_idx(Query a, Query b) { return a.idx < b.idx; }
int main()
{
freopen("expect.in", "r", stdin);
freopen("expect.out", "w", stdout);
scanf("%d %d",&n,&q);
for(int i=1;i<=n;i++) {
scanf(" %c %d %d", &op, &t[i], &k[i]);
if(op == '+') k[i] *= -1;
}
int wait = k[1];
for(int i=2;i<=n;i++)
{
p[i-1].wait = wait;
p[i-1].len = t[i]-t[i-1];
wait += k[i];
}
wait = max(0, wait);
sort(p+1, p+n);
for(int i=1;i<=q;i++)
scanf("%d", &qry[i].q), qry[i].idx = i;
sort(qry+1, qry+q+1, cmp);
qry[0].q = qry[1].q;
long long ans = 0, len = 0;
int idx = 1;
for(int i=1;i<=q;i++)
{
if(qry[i].q < wait) { qry[i].ans = -1; continue; }
ans += len * (qry[i-1].q - qry[i].q);
while(idx < n && p[idx].wait > qry[i].q) {
ans += (long long)(p[idx].wait - qry[i].q) * p[idx].len;
len += p[idx].len;
idx++;
}
qry[i].ans = ans;
}
sort(qry+1, qry+q+1, cmp_idx);
for(int i=1;i<=q;i++)
if(qry[i].ans == -1) printf("INFINITY\n");
else printf("%I64d\n", qry[i].ans);
}