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