time limit per test
1 second
memory limit per test
256 megabytes
This is the hard version of the problem. The only difference is that in this version n≤200000. You can make hacks only if both versions of the problem are solved.
There are n potions in a line, with potion 1 on the far left and potion n on the far right. Each potion increases your health by ai when drunk. ai can be negative, meaning that the potion decreases your health.
You start with 0 health, and you will walk from left to right, from the first potion to the last one. At each potion, you may choose to drink it or ignore it. You must ensure that your health is always non-negative.
What is the largest number of potions you can drink?
Input
The first line contains a single integer n (1≤n≤200000) --- the number of potions.
The next line contains n integers a1, a2, ... ,an (−109≤ai≤109) which represent the change in health after drinking that potion.
Output
Output a single integer, the maximum number of potions you can drink without your health becoming negative.
Example
Input
Copy
6
4 -4 1 -3 1 -3
Output
Copy
5
Note
For the sample, you can drink 5 potions by taking potions 1, 3, 4, 5 and 6. It is not possible to drink all 6 potions because your health will go negative at some point
解题说明:此题是一道模拟题,可以采用贪心算法,从左到右遍历,先全部喝掉。如果血量变负,就丢掉之前喝过的负收益最大的那瓶(因为丢掉它能让血量增加最多)。这里需要用到小根堆,用来维护的是已喝的负值药水,堆顶就是最该丢掉的那个。
cpp
#include<bits/stdc++.h>
#include<algorithm>
#include<vector>
#include<iostream>
using namespace std;
typedef long long ll;
priority_queue<int, vector<int>, greater<int> >pq;
int main()
{
ll n, s = 0, c = 0;
cin >> n;
while (n--)
{
int x;
cin >> x;
pq.push(x);
c += x;
s++;
if (c < 0)
{
c -= pq.top();
pq.pop();
s--;
}
}
cout << s<<endl;
return 0;
}