HDU6438:Buy and Resell(贪心+数据结构)
题意 : 给出一些数、你可以从左到右对这些数进行三种操作花费 Ai 买入东西、以 Ai 价格卖出你当前有的东西、或者什么都不做、现在问你可以获取的最大利益是多少
分析:对每一个元素产生的贡献可以先计算出暂时的最优值,注意是暂时的最优,应为后面可以出现更加优的答案,所有下次遇到更优的时候就进行替换;
具体就是首先使用小顶堆维护枚举过的元素
然后对于当前枚举到的元素
用它和堆顶元素做对比、如果小于或等于堆顶元素
那么它无法和之前枚举过的所有元素的任何一个做减法产生贡献
所以将其加入这个小顶堆当中去
如果大于堆顶元素、则用它和堆顶元素做减法、算出它和堆顶元素产生贡献
当然这个贡献只是暂时最优的、堆顶元素和当前枚举到的元素进行配对并不一定是最优的
那么怎么样在下一次枚举到更优的配对元素时进行替换
答案就是做完贡献之后、将堆顶元素弹出、然后 push 两次当前枚举到的元素进入堆内
第一个 push 的意义是下次如果其作为堆顶元素、那么可以把它拿出来做减法达到反悔操作
第二个 push 的意义就是真正的卖出
每天都卖出,每次累加差值就可以了。累加很多个差分值肯定会得到最优解的。
因为A买入B卖出B买入C卖出 和 A买入C卖出 效果一样的
#include<bits/stdc++.h> using namespace std; #define pll pair<long long , long long > #define ll long long int main( ) { int t ; scanf("%d",&t); while(t--) { int n ; scanf("%d",&n); priority_queue<pll , vector<pll> , greater<pll> > qu ; ll ans = 0 ; int num = 0; for(int i=0 ; i<n ; i++) { ll val; scanf("%lld",&val); if(!qu.empty() && qu.top().first < val) { num++; pll T=qu.top() ; qu.pop(); if(T.second == 1) num--; else num++; ans+=val-T.first; printf("(%lld %d %d)\n", ans,num,val); qu.push(make_pair(val,1)); qu.push(make_pair(val,2)); } else qu.push(make_pair(val,3)); } printf("%lld %d\n",ans , num); } }