Jzoj4835 量化交易

一眼就可以看出是贪心,问题就是怎么去操作

首先一个很显然的思路就是,开一个小根堆,每次对于一个价格x,如果低于堆顶我们就将其丢进去,否则将堆顶y取出,获得x-y的贡献

但是这样是有问题的,我们会发现有反例: 1 4 2 3 用这种方法求出的答案是1但是正确答案应该是2

所以我们需要增加一种“撤销操作”

类似于种花那道题,我们每次将答案加上了x-y时候,我们也将x丢入堆中,而且要丢入两次,为什么?

举个例子:1 2 3 4

我们在做到2的时候,我们将第一天的股票卖了得到1的收益,但是实际上,2这一天不应该卖反而应该买,所以原本在第2天的交易量由-1变为了1,变化量为2

也就是说,对于一个对答案做出贡献的x,我们将其丢入堆中*2,则第一次取出,相当于撤回一次出售,比如对于第三天的3(收益为3-(2-1)=2)

第二次取出,则相当于将其也作为买入的一天,比如第四天(4-2=2)

所以总收入为2+2=4

这题卡常,建议手打堆(我过了是因为jz跑得快)

#include<stdio.h>
#include<queue>
using namespace std;
int main(){
	freopen("trade.in","r",stdin);
	freopen("trade.out","w",stdout);
	for(int n,T=1;~scanf("%d",&n);++T){
		unsigned ans=0;
		priority_queue<int,vector<int>,greater<int> > q;
		for(int x,i=0;i<n;++i){
			scanf("%d",&x);
			if(q.empty()||x<=q.top()) q.push(x);
			else {
				ans+=x-q.top(); q.pop();
				q.push(x); q.push(x);
			}
		}
		printf("Case #%d: %u\n",T,ans);
	}
}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值