题解:CF1974G Money Buys Less Happiness Now

简述题意

对于第 ii 个月,你可以选择执行:mmci,ansans+1m\gets m-c_i,ans\gets ans+1。每个月后,你必须执行:mm+x(x>0)m\gets m+x(x>0)

ansans 的最大值。

算法分析

subtask1

枚举每个月是否交钱。时间复杂度 O(2nn)O(2^n n)

subtask2

我们肯定很想每次都交钱,故可以考虑每一次先交钱。

交完钱之后呢?如果亏了钱,就在之前交钱的最多的一次删去。

Q1:怎么维护呢?
A1:插入、求最大值、删除最大值——堆(优先队列)!

Q2:那会不会删去后还亏了钱?
A2:因为你删去的是堆顶,而你付的是在这个堆中的,不可能大于堆顶。

Q3:凭什么此时最优?
A3:因为此时堆中元素都小于堆外元素,不可能一个堆中元素出去之后能放两个堆外元素进来。

最后输出堆的大小即可。

代码实现

#include<bits/stdc++.h>
#define int long long
using namespace std;
int c[200005];
priority_queue<int>q;
signed main()
{
	int T;
	cin>>T;
	while(T--)
	{
		while(!q.empty()) q.pop();
		int n,x,ys,my=0,ans=0;
		cin>>n>>x;
		for(int i=1;i<=n;i++) cin>>c[i];
		for(int i=1;i<=n;i++)
		{
			my-=c[i];
			q.push(c[i]);
			if(my<0) my+=q.top(),q.pop();
			my+=x;
		}
		cout<<q.size()<<endl;
	}
	return 0;
}

P.S:记得清空优先队列。

posted @ 2024-07-02 15:37  sLMxf  阅读(21)  评论(0)    收藏  举报  来源