【CF865D】Buy Low Sell High

题目

题目链接:https://codeforces.com/problemset/problem/865/D
已知接下来 \(n\) 天的股票价格,每天你可以买进一股股票,卖出一股股票,或者什么也不做。\(n\) 天之后你拥有的股票应为 \(0\)。最大化 \(n\) 天内赚的钱。
\(n\leq 3\times 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(n\log 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;
}
posted @ 2021-05-31 11:12  stoorz  阅读(109)  评论(0编辑  收藏  举报