CF865D Buy Low Sell High

CF865D Buy Low Sell High

Buy Low Sell High

题目
已知接下来N天的股票价格,每天你可以买进一股股票,卖出一股股票,或者什么也不做.N天之后你拥有的股票应为0,当然,希望这N天内能够赚足够多的钱.

分析

  • 假如我们当前这个\(a_j\)作为某天卖出,那么一定是和前面的还没有用的最小的\(a_i\)来进行配对,并且只有当\(a_j>a_i\) 时才进行配对,且得到利润为\(a_j-a_i\),因此我们可以用一个堆记录哪些还没有用
  • 但是我们在这一天卖出不一定是最优的
  • 假象我们在这一天同时又买入了一个价值为val的股票,并在之后第k天卖出
  • 如果有\(a_j-a_i+a_k-val=a_k-a_i\)也就是\(val=a_j\)的时候我们相当于撤销了在第j天卖出,转而在第k天卖出
  • 另外为什么当前最小的\(a_i\)一定出现在最后的配对里呢?
  • 假设最终答案中不包含\(-a_i\)这一项
  • 假如也不包含\(a_j(i<j)\)这一项,那么我们可以让它们配对,与当前答案是最右答案矛盾
  • 因为\(a_i\)\(a_j\)选择时最小的一项,所以它一定会跟\(a_i\)配对
  • 如果是出现了像\(a_k-a_j\)这样的项,我们直接替换为\(a_k-a_i\)答案只会变大,与答案的最优性矛盾
#include<bits/stdc++.h>
#define fo(i,a,b) for (ll (i)=(a);(i)<=(b);(i)++)
#define fd(i,b,a) for (ll (i)=(b);(i)>=(a);(i)--)
#define eb emplace_back
#define mk(x,y) make_pair((x),(y))
#define A puts("YES")
#define B puts("NO")
#define lc (o<<1)
#define rc ((o<<1)|1)
#define pi pair<ll,ll>
using namespace std;
typedef long long ll;
typedef double db;
const int N=5005;
const ll P=131;
const ll Q=13331;
const ll inf=1ll<<60;
const ll mo1=1e9+7;
const ll mo2=1e9+9;
const ll mo=998244353;
ll n,x,ans;
priority_queue<ll, vector<ll>, greater<ll>> q;
int main(){
//	freopen("data.in","r",stdin);

	scanf("%lld",&n);
	fo(i,1,n) {
		scanf("%lld",&x);
		if (!q.empty() && x>q.top()) {
			ans+=x-q.top();
			q.pop();
			q.push(x);
		}
		q.push(x);
	}
	printf("%lld",ans);


	return 0;
}
 
posted @ 2024-08-27 09:10  gan_coder  阅读(6)  评论(0编辑  收藏  举报