Codeforces Round #723 (Div. 2) C2. Potions (Hard Version)

翻译:

这是这个问题的难解版本。唯一的区别是在这个版本中𝑛≤200000。只有两个版本的问题都解决了,你才能进行hack。

一行中有𝑛种药剂,药剂1在最左边,药剂𝑛在最右边。每一剂药水在饮用后将增加你的生命值𝑎𝑖。𝑎𝑖可能是负面的,意思是药水会降低生命值。

玩家从0生命值开始,从左到右走,从第一剂药剂走到最后一剂药剂。对于每一剂药剂,你可以选择喝或忽略它。你必须确保你的健康状况一直不是负面的。

你最多能喝多少药水?

输入
第一行包含一个整数𝑛(1≤𝑛≤200000)—药水的数量。

下一行包含𝑛整数𝑎1,𝑎2,…,𝑎𝑛(−109≤𝑎𝑖≤109),表示饮用该药水后的生命值变化。

输出
输出一个整数,即在你的生命值为负的情况下,你可以喝的药水的最大数量。

例子
inputCopy
6
4 -4 1 -3 1 -3
outputCopy
5
请注意
对于样品,你可以通过服用药水1、3、4、5和6喝5种药水。这是不可能喝所有的6种药水,因为你的健康会在某些时候变得消极

 思路:刚开始感觉好像可以用dp,但是一看数据范围就寄了。那么这肯定是一道奇妙思维题,我们根据题目可以得到以下:可以喝或不喝 从左到右走 喝的最大的数量

所以我们可以得到什么,按顺序走,如果前边的路过没有喝,那么就不能再喝,所以我们无法确定喝还是不喝,非负数肯定全喝,然后在负数中 喝大的和小的一样,所以我们对这个性质便可以有所操作,我们前边能喝就喝,然后使用优先队列小顶堆,如果喝不下了,就把负的最小的扔出去,再喝当前负的较小的,这样反复,到最后就是最优的。

代码:

#include <iostream>
#include <algorithm>
#include <string.h>
#include <string>
#include <math.h>
#include <stdio.h>
#include<vector>
#include<queue>
#include<stack>
#include<map>
#include<set>
#include<tuple>
#include<numeric>
using namespace::std;
typedef long long  ll;
inline __int128 read(){
    __int128 x = 0, f = 1;
    char ch = getchar();
    while(ch < '0' || ch > '9'){
        if(ch == '-')
            f = -1;
        ch = getchar();
    }
    while(ch >= '0' && ch <= '9'){
        x = x * 10 + ch - '0';
        ch = getchar();
    }
    return x * f;
}
inline void print(__int128 x){
    if(x < 0){
        putchar('-');
        x = -x;
    }
    if(x > 9)
        print(x / 10);
    putchar(x % 10 + '0');
}
int n;
ll x;
int main(){
    ios::sync_with_stdio(false);
    cin.tie(); cout.tie();
    priority_queue<ll,vector<ll>,greater<>>q;
    cin>>n;
    ll an=0;
    for (int i =0; i<n; i++) {
        cin>>x;
        q.push(x);
        an+=x;
        while (an<0) {
            an-=q.top();
            q.pop();
        }
    }
    printf("%lu\n",q.size());
    return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值