2018ccpc网络赛 Buy and Resell
题意:有n天,在一天之内可以买东西或卖东西,也可以什么都不做,手里可以有多样物品,问n天过后最大赚多少钱。
思路:用一个优先队列维护一个堆,当堆中最小元素小于本位置元素就可以进行交换ans+=(x-q.top);如果q.top这个元素曾经交换过那么本次交换也就不算次数,然后要将x放入堆两个,相当于一个缓冲作用其实并没有加该数的值。比如 5 9 10,就是先放5,然后9赚4,当10进入,最小值9交换赚1,最终相当于买5卖10.,如果是9,5,9,10,即10-9+5-9,因此不必在放堆中两次
#include <iostream> #include <cstring> #include <cstdio> #include <queue> #include <map> using namespace std; priority_queue<int>q; map<int,int>vis;//标记该值之前买过几次 int main() { int T; scanf("%d",&T); while(T--) { int n; scanf("%d",&n); priority_queue<int, vector<int>, greater<int> > q;//元素小的优先级高 while(!q.empty()) q.pop();//清空 long long ans=0,cnt=0; vis.clear(); for(int i=1;i<=n;i++) { int x; scanf("%d",&x); if(q.empty()||q.top()>=x) q.push(x); else { cnt++; int t=q.top(); ans+=(x-t); q.pop(); if(vis[t]) { cnt--; vis[t]--; } q.push(x); q.push(x);//主要这里 vis[x]++; } } printf("%lld %lld\n",ans,cnt*2); } }