C2. Potions (Hard Version)(可以后悔的选取 + 一种新奇的优先队列用法)

这是一个关于算法优化的问题,描述了如何在确保健康状况始终非负的情况下,找出最多能喝多少瓶药水。策略是采用小根堆来动态调整选择的药水,如果当前健康状况变为负数,则移除堆中最小的元素。这种方法允许‘后悔’,即在必要时撤销先前的选择以保持健康。代码实现使用了优先队列和动态规划的概念。
摘要由CSDN通过智能技术生成

Problem - 1526C2 - Codeforces

这是该问题的困难版本。唯一不同的是,在这个版本中,n≤200000。只有当两个版本的问题都解决了,你才能进行黑客攻击。

有n个药水排成一行,最左边是药水1,最右边是药水n。每种药水在喝下后都会使你的健康状况增加ai。ai可以是负数,这意味着该药水会减少你的健康状况。

你开始时健康状况为0,你将从左到右,从第一个药水走到最后一个。在每个药水处,你可以选择喝下它或忽略它。你必须确保你的健康状况始终是非负值。

你能喝的最大药水数量是多少?

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

下一行包含n个整数a1, a2, .... ,an (-109≤ai≤109),代表喝完药水后的健康变化。

输出
输出一个整数,即你能喝的最大药水数量,而你的健康状况不会变成负数。

例子
inputCopy
6
4 -4 1 -3 1 -3
outputCopy
5
注意
在这个例子中,你可以通过服用药水1、3、4、5和6喝下5瓶药水。不可能喝完所有的6种药水,因为你的健康状况会在某一时刻变成负数。

题解:
我们默认每次选的时候都选cnt++,并把a[i]存到小根堆中,如果此时s < 0,我们就减去小根堆里,最小的元素,并弹出,cnt--

可以后悔的选取方法,很新奇一种思路,一旦与不符合条件,就减去之前加过最小的,

 

#include<iostream>
#include<algorithm>
#include<string>
#include<queue>
#include<vector>
#include<map>
#include<cstring>
#include<cmath>
#include<set>
using namespace std;
#define int long long
int a[200050];
int b[200050];
void solve()
{
	int n;
	cin >> n;
	int f = 0;
	priority_queue<int,vector<int>,greater<int>> q; 
	for(int i = 1;i <= n;i++)
	{
		cin >> a[i];
	}
	int cnt = 0;
	for(int i = 1;i <= n;i++)
	{
		f += a[i];
		q.push(a[i]);
		if(f < 0)
		{
			cnt--;
			f -= q.top();
			q.pop();
		}
		cnt ++;
	}
	cout << cnt;
}
//3 -2 3 
signed main()
{
//	ios::sync_with_stdio(false);
//	cin.tie(0);
//	cout.tie(0);
	int t = 1;
//	cin >> t;
    while(t--)
	{
		solve();
	} 
}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值