CF865D Buy Low Sell High

这道贪心非常神仙

大体想法肯定是选择一个价格较低的一天买入
并在之后找一个价格较高的一天卖出

直接贪心的选显然不可行,考虑如何实现“反悔”

这里直接说做法,反正我也想不到= =

从前向后扫描每一天,若当前价格比堆顶还小就入堆

否则,将从堆顶买入并从当天卖出,弹出堆顶,并将当天价格入堆两次

这里解释一下入堆两次的道理

如果之后有一天价格更高,可以借助其中入堆的一个值反悔,
相当于从那次的堆顶买入,价格更高的这天卖出,大概是下图的意思

红线左右是同一天,
在第一天买入到第二天发现可以卖就卖掉了
在第三天发现更优,就在第二天买入并在第三天卖出
相当于第二天没有操作,而剩下入堆的一个值就可以在以后有更高的价格时从这天买入

而如果有这次反悔,相当于那天并没有进行操作
这时候多入堆的那次就有用了

这样以后它作为堆顶之后,就相当于在那天买入后边卖出了


 代码:

#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdlib>
#include<cctype>
#include<cstdio>
#include<queue>
using namespace std;

typedef long long ll;
const int MAXN = 300005;

int n;
int p[MAXN];
ll ans;
priority_queue<int> q;

int main() {
    scanf("%d", &n);
    for(int i = 1; i <= n; ++i) 
        scanf("%d", &p[i]);
    for(int i = 1; i <= n; ++i) {
        if(q.empty() || -q.top() > p[i]) q.push(-p[i]);
        else {
            ans += q.top();
            q.pop();
            ans += p[i];
            q.push(-p[i]);
            q.push(-p[i]);
        }
    }
    printf("%lld\n", ans);
    return 0;
}
posted @ 2018-10-10 19:46  EvalonXing  阅读(704)  评论(0编辑  收藏  举报