这道贪心非常神仙
大体想法肯定是选择一个价格较低的一天买入
并在之后找一个价格较高的一天卖出
直接贪心的选显然不可行,考虑如何实现“反悔”
这里直接说做法,反正我也想不到= =
从前向后扫描每一天,若当前价格比堆顶还小就入堆
否则,将从堆顶买入并从当天卖出,弹出堆顶,并将当天价格入堆两次
这里解释一下入堆两次的道理
如果之后有一天价格更高,可以借助其中入堆的一个值反悔,
相当于从那次的堆顶买入,价格更高的这天卖出,大概是下图的意思
红线左右是同一天,
在第一天买入到第二天发现可以卖就卖掉了
在第三天发现更优,就在第二天买入并在第三天卖出
相当于第二天没有操作,而剩下入堆的一个值就可以在以后有更高的价格时从这天买入
而如果有这次反悔,相当于那天并没有进行操作
这时候多入堆的那次就有用了
这样以后它作为堆顶之后,就相当于在那天买入后边卖出了
代码:
#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 ", ans); return 0; }