Gym - 101190E Expect to Wait(数形结合 , 二分, 查分)

题意:

告诉你n 个操作过程, + 代表 在t 时刻来了k 个车,  - 代表在t 时刻 来了k 个人,  每个人都要开走车, 没车的话 一直在队列里等, 告诉你每一天开始有多少辆车, 求所有人的等待时间总和, 如果有人拿不到车就输出 inf。

思路:


数形结合的思想。

n 个操作可以分成n-1 段, 记录每一段的人和 等待时间。

那么一开始有x 辆车的话, 那么只需要将大于x 的段减掉x 乘以等待时间即可。

那么这样 与每一段的顺序无关, 直接按照人排序, 然后枚举x, 二分查找左边界, 做个前缀和 差分即可。

#include <cstdio>
#include <cstring>
#include <algorithm>
#include <queue>
#include <string>
#include <iostream>
#include <cctype>
#include <sstream>
#include <vector>
using namespace std;
const int maxn = 100005;


struct node1{
    char cmd[4];
    int t, k;
}p[maxn];

struct node{
    int num, len;

}nod[maxn];

bool cmp(const node& lhs, const node& rhs){
    return lhs.num < rhs.num;
}
long long pre[maxn];
long long pre1[maxn];

int main(){
    freopen("expect.in","r",stdin);
    freopen("expect.out","w", stdout);

    int n,q;
    while(~scanf("%d %d",&n, &q)){
        int x, y;
        int sum = 0;
        long long peo = 0LL;
        for (int i = 0; i < n; ++i){
            scanf("%s%d%d", p[i].cmd, &p[i].t, &p[i].k);
            if (p[i].cmd[0] == '-'){
                peo += p[i].k;
            }
            else {
                peo -= p[i].k;
            }
        }
        if (p[0].cmd[0] == '-')
            sum = p[0].k;
        else
            sum = -p[0].k;
        int cnt = 0;
        for (int i = 1; i < n; ++i){
            nod[++cnt].num = sum;
            nod[cnt].len = p[i].t - p[i-1].t;
            if (p[i].cmd[0] == '-'){
                sum += p[i].k;
            }
            else {
                sum -= p[i].k;
//                sum = max(sum, 0);
            }
        }

        sort(nod + 1, nod + cnt + 1, cmp);


        for (int i = 1; i <= cnt; ++i){
            pre[i] = pre[i-1] + (long long)nod[i].num * nod[i].len;
            pre1[i] = pre1[i-1] + nod[i].len;
        }

//
//        for (int i = 1; i <= cnt; ++i){
//            printf("%d %d\n", nod[i].num, nod[i].len);
//
//        }
//        printf("peo = %lld\n", peo);

        for (int i = 0; i < q; ++i){
            long long ans = 0LL;
            int x;
            scanf("%d",&x);

            if (x < peo) {
                printf("INFINITY\n");
                continue;
            }
            int l = 1, r = cnt;
            while (l <= r){
                int m = l + r >> 1;
                if (nod[m].num > x){
                    r = m - 1;
                }
                else {
                    l = m + 1;
                }
            }
//            printf("r = %d\n", r);
            ans = (pre[cnt] - pre[r]) - x * (pre1[cnt] - pre1[r]);
            printf("%I64d\n", ans);
        }
    }
    return 0;
}

/**
This is ACM North Eastern European Regional Contest,
sponsored by International Business Machines.
The. Best. Contest. Ever.
A Great Opportunity for all contestants.
ab Ab A Abc AB Abcd ABc Abcde AbC
Oh  No  Extra Spaces.And,Punctuation Ruin Everything
10 4 1 2
1 2 3 4 5 6 7 8 9 10
10 9 8 7 6 5 4 3 2 1
EEESEEEESS
68


6  100
- 2 3
- 4 3
+ 5 2
+ 7 4
- 10 3
+ 13 3


6  100
- 2 3
- 4 3
+ 5 2
+ 7 4
- 10 3
+ 13 3


5 100
+ 2 1
+ 4 2
+ 5 3
+ 9 10
+ 10 11

**/


  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值