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);
	}
}

posted @ 2017-10-30 07:49  扩展的灰(Extended_Ash)  阅读(100)  评论(0编辑  收藏  举报