「反悔贪心」

反悔贪心

贪心是按照一定顺序进行选择的思想,但是局部最优不等于全局最优,有的时候我们需要用到反悔贪心,看一道例题。

Buy Low Sell High

思路

我们发现不能简单的通过最小的股票或者最大的股票,又或是次大的股票进行操作。
这时,我们考虑一个问题,在 \(i < j < k\) 中,利润分别是什么?

  • \(i\) 天买进,在 \(j\) 天卖出,利润为 \(p_j - p_i\)
  • \(j\) 天买进,在 \(k\) 天卖出,利润为 \(p_k - p_j\)

我们可以采用反悔操作,即当在 \(p_j > p_i\) 时,说明 \(j\) 天有利可谋,我们就在 \(j\) 天同时买进和卖掉股票。但是我们的答案只记录赚的钱,于是当我们在 \(j\)\(k\) 天都卖出的时候,利润为 \((p_k - p_j) + (p_j - p_i) = (p_k - p_i)\),则相当于在 \(i\) 天买入,在 \(k\) 天卖出。于是我们可以用小根堆维护该天前的能卖或者能反悔的压入堆。
可得以下代码:

#include<iostream>
#include<vector>
#include<stack>
#include<set>
#include<algorithm>
#define int long long
using namespace std;

int n;
int p,ans = 0;
multiset<int> q;

signed main(){
	cin >> n;
	for(int i = 1;i <= n;i ++){
		cin >> p;
		if(!q.empty() && *q.begin() < p){
			ans += (p - *q.begin());
			q.erase(q.begin());
			q.insert(p);//日后反悔
		}
		q.insert(p);//日后交易
	}
	cout << ans << '\n';
	return 0;
}
posted @ 2025-01-22 19:17  To_Carpe_Diem  阅读(41)  评论(0)    收藏  举报