Codeforces Gym 101190 (NEERC 2016) E. Expect to Wait (扫描线)

41 篇文章 0 订阅
1 篇文章 0 订阅

题意

按时间顺序给出在某地借还车记录。

  • + 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);
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值