HDU6438--Buy and Resell(2018ccpc网络赛)贪心+优先队列

21 篇文章 0 订阅
8 篇文章 0 订阅

题意:每到一个位置可以买一个东西或卖一个东西或什么也不做;问最大利润及最大利润情况下使用的最短时间;
思路:贪心,用一个优先队列结构去存之前准备买的东西(但还没买),遇到比堆中最小值大的值时,就把堆顶元素pop掉(这里开始才算完成交易),同时把当前值入队两次,为什么是两次?
由于当前值的选择不一定是最优的选择,后面可能有更好的选择,故第一次是用来作为中间位置存入以便进行进一步更大利润的交易。
第二次是将当前值作为带买商品存入堆,可能之后会交易到(但交易到之前作为中间位置的值也已经被交易)
由于题目还问了所需的最短时间,故用一个map来存每个元素当作中间元素的总次数,当总次数不为0是,该元素出队不加时间(因为它只是中间元素)。
代码如下:(注意优先队列变成小根堆要用G++提交,不然会编译错误…)

#include <cstdio>
#include <cstring>
#include <algorithm>
#include <queue>
#include <map>
using namespace std;
typedef long long ll;
//贪心加优先队列:买低卖高问题;
int main()
{
    int i,j;
    int t;
    int n;
    ll now;
    ll ans;
    int cnt;
    scanf("%d",&t);
    while(t--)
    {
        priority_queue< ll,vector<ll>,greater<ll> >q;
        map<ll,int>mp;//用来记录当前元素作为中间买卖位置的次数
        mp.clear();//避免容器中有未初始化的空间
        while(!q.empty())
        {
            q.pop();
        }
        ans=0;
        cnt=0;
        scanf("%d",&n);
        for(i=1;i<=n;i++)
        {
            scanf("%lld",&now);
            if(!q.empty()&&now>q.top())
            {
                int tp=q.top();
                ans+=now-tp;
                cnt++;
                q.pop();
                q.push(now);
                q.push(now);
                if(mp[tp]!=0)//即堆顶元素是作为其他元素买卖的中间位置,并不是真正卖掉
                {
                    cnt--;
                    mp[tp]--;
                }
                mp[now]++;//now暂时作为中间位置,mp++;
            }
            else
            {
                q.push(now);
            }
        }
        printf("%lld %d\n",ans,cnt<<1);//cnt要乘2因为买卖都要算一次;
    }
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值