Codeforces Round #723 C1, C2 positions

Title:

website: http://codeforces.com/contest/1526/problem/C1

translate:
A person's initial health is 0 and there are n medicine bottles. Each medicine bottle has its own impact on health (a[i]). Now you can choose to drink or ignore each bottle of medicine from left to right, so as to find out how many bottles of medicine you can drink at most when the health value of the whole process is greater than or equal to 0

Idea:

When writing C1, because n is 2000, my first feeling is to write dp (because I really didn't think of another method qwq), so I began to push the transfer equation and write a dp of n2.

Also write down your thoughts (although you can't pass C2):
f [ i ] [ j ] f[i][j] f[i][j] records the maximum health value that can be obtained by drinking j bottles of medicine in the first I bottles of medicine. Then we can get an equation:
f [ i ] [ j ] = m a x ( f [ i − 1 ] [ j ] , f [ i − 1 ] [ j − 1 ] + a [ i ] ) f[i][j]=max(f[i-1][j],f[i-1][j-1]+a[i]) f[i][j]=max(f[i−1][j],f[i−1][j−1]+a[i])
(there is a special judgment to be made here, that is f [ i − 1 ] [ j ] f[i-1][j] f[i − 1][j] and f [ i − 1 ] [ j − 1 ] f[i-1][j-1] f[i − 1][j − 1] cannot be less than 0 before transfer)
So for this dp equation, we just need to record f [ i ] [ j ] f[i][j] f[i][j] is the maximum j value of positive value (the number of bottles to drink)

dp Code:
#include<bits/stdc++.h>
#define ll long long
#define endl '\n'
using namespace std;
const int mod=1e9+7;
const int N=2e3+5;
int n,ans,a[N];
ll f[N][N];
void solve()
{
	cin>>n;
	for(int i=1;i<=n;i++)
	    cin>>a[i];
	memset(f,-1,sizeof(f));
	if(n==1)
	{
		if(a[1]<0) cout<<0;
		else cout<<1;
		return;
	}
	f[1][0]=0,f[1][1]=a[1];
	for(int i=2;i<=n;i++)
	{
		f[i][0]=0;
		for(int j=1;j<=i;j++)
		{
			if(f[i-1][j]<0&&f[i-1][j-1]<0) f[i][j]=-1;  //Special judgment
			else f[i][j]=max(f[i-1][j],f[i-1][j-1]+a[i]);
			if(f[i][j]>=0) ans=max(ans,j);
		}
	}
	cout<<ans;
}
int main()
{
	ios::sync_with_stdio(false);
	cin.tie(0); cout.tie(0);
	int __=1;
	//cin>>__;
	while(__--)
	    solve();
	return 0;
}

But when I think about two questions in a code happily, when I turn to C2, I see the data 2e5. I'm stupid. dp iron T of n2 has to think of a new solution 55555

Because this question asks for the maximum number of drugs to drink, we should consider how to get as high as possible in the case of taking the most drugs

Then we can try to be greedy:
For drugs with a [i] > = 0, we can drink them directly without much consideration
For those drugs with a [i] < 0, it can be considered in two cases:
1. If HP (health value) is > = 0, you can drink it directly
2. For those who drink HP < 0, we can consider whether it can help us achieve the highest life value under the condition of taking the most drugs
It is to compare the smallest drug of a[i] among the drugs currently drunk with it and judge whether this drug can be used to replace the smallest drug of a[i] (regret step)
For the operation in this case, we can use the priority queue to maintain the a[i] smallest medicine currently taken

Put the code:
#include<bits/stdc++.h>
#define ll long long
#define endl '\n'
using namespace std;
const int mod=1e9+7;
const int N=2e5+5;
int n,ans,a[N];
ll hp;
void solve()
{
	priority_queue<ll,vector<ll>,greater<ll>> q;   //Keep the medicine you have taken in ascending order
	cin>>n;
	for(int i=1;i<=n;i++)
	{
		cin>>a[i];
		if(a[i]>=0)  
		{
			ans++; hp+=a[i];
			q.push(a[i]);
		}
		else
		{
			if(hp+a[i]>=0)
			{
				ans++; hp+=a[i]; 
			    q.push(a[i]);
			}
			else if(!q.empty()&&a[i]>q.top())
			{
				int u=q.top(); q.pop();
				hp+=a[i]-u;
				q.push(a[i]);
			}
		}
	}
	cout<<ans;
}
int main()
{
	ios::sync_with_stdio(false);
	cin.tie(0); cout.tie(0);
	int __=1;
	//cin>>__;
	while(__--)
	    solve();
	return 0;
}

Added by Wade on Tue, 08 Feb 2022 06:36:08 +0200