【CF865D】Buy Low Sell High 题目 思路 代码

题目链接:https://codeforces.com/problemset/problem/865/D
已知接下来 (n) 天的股票价格,每天你可以买进一股股票,卖出一股股票,或者什么也不做。(n) 天之后你拥有的股票应为 (0)。最大化 (n) 天内赚的钱。
(nleq 3 imes 10^5)

思路

反悔贪心模板题。
首先考虑一个显然错误的贪心策略:对于第 (i) 天,选择前面能选的股票价格最小的那一天 (j),若 (a_i>a_j) 则在第 (j) 天买入,第 (i) 天卖出。可以用一个堆维护前缀最小值。
但是这样有一个明显的问题,可能第 (j) 天匹配第 (k(k>i)) 天会更优。也就是局部最优解不一定为全局最优解。
所以采用一个反悔操作,当我们匹配了第 (i) 天和第 (j) 天时,我们再把 (a_i) 扔进堆里,这样如果 (j) 本应该匹配 (k) 时,计算到的价值就是 ((a_k-a_i)+(a_i-a_j)=a_k-a_j)
时间复杂度 (O(nlog n))

代码

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;

const int N=300010;
int n;
ll ans,x;
priority_queue<ll> q;

int main()
{
	scanf("%d",&n);
	for (int i=1;i<=n;i++)
	{
		scanf("%I64d",&x);
		if (q.size() && x+q.top()>0)
		{
			ans+=x+q.top();
			q.pop(); q.push(-x);
		}
		q.push(-x);
	}
	cout<<ans;
	return 0;
}