HDU 6438 Buy and Resell (贪心+优先队列)

题意:给定n天,每天有个价格,可以买一个物品,可以把手中的物品卖掉,求最大利润和最少买卖次数。

思路:最大利润按这个https://blog.csdn.net/Dilly__dally/article/details/82055866思路求,先看第二个样例9 5 9 10 5 ,按队列模拟利润是 9-5 + 10-9 ,可以看出9是一个中间物,不用买9,所以只需在原来思路的基础上加上对入队和出队的访问就可以了,具体:因为数据到了1e9,不能用数组,所以用map<int,int> 来代替访问数组,每次要卖的时候就给mp[a]++(至于不能用0、1判断,因为可能会有多个相同的价格),如果对头的元素已经访问过(卖过),那么cnt--,对头的访问量也--。最后cnt要*2(因为cnt计算的是卖的次数,有卖肯定有买~)。

#include<bits/stdc++.h>
using namespace std;
#define inf 0x3f3f3f3f
#define ll long long
const int maxn=200005;
const double eps=1e-8;
const double PI = acos(-1.0);
#define lowbit(x) (x&(-x))
map<int,int> mp;
int main()
{
    std::ios::sync_with_stdio(false);
    std::cin.tie(0);
    std::cout.tie(0);
    int t;
    cin>>t;
    int n;
    while(t--)
    {
        priority_queue<int,vector<int>,greater<int> > pq;
        mp.clear();
        cin>>n;
        ll ans=0,cnt=0;
        for(int i=0;i<n;i++)
        {
            int a;
            cin>>a;
            if(!pq.empty()&&pq.top()<a)
            {
                int t=pq.top();
                pq.pop();
                pq.push(a);
                cnt++;
                ans+=(a-t);
                if(mp[t]>0)
                {
                    cnt--;
                    mp[t]--;
                }
                mp[a]++;
            }
            pq.push(a);

        }
        cout<<ans<<" "<<cnt*2<<endl;
    }
    return 0;
}

 

posted @ 2018-08-26 12:07  MCQ  阅读(116)  评论(0编辑  收藏  举报