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
",ans,cnt*2);
    }
}
原文地址:https://www.cnblogs.com/Fy1999/p/9562128.html