HDU 6438 Buy and Resell CCPC网络赛(贪心)

HDU 6438 Buy and Resell CCPC网络赛(贪心)

 

题意 : 给出一些数、你可以从左到右对这些数进行三种操作花费 Ai 买入东西、以 Ai 价格卖出你当前有的东西、或者什么都不做、现在问你可以获取的最大利益是多少?

 

分析:和CF 867E差不多

对于每个元素产生的贡献

可以先算出暂时的最优值

如果下次碰到更优的选择再进行替换

具体就是首先使用小顶堆维护枚举过的元素

然后对于当前枚举到的元素

用它和堆顶元素做对比、如果小于或等于堆顶元素

那么它无法和之前枚举过的所有元素的任何一个做减法产生贡献

所以将其加入这个小顶堆当中去

如果大于堆顶元素、则用它和堆顶元素做减法、算出它和堆顶元素产生贡献

当然这个贡献只是暂时最优的、堆顶元素和当前枚举到的元素进行配对并不一定是最优的

那么怎么样在下一次枚举到更优的配对元素时进行替换

答案就是做完贡献之后、将堆顶元素弹出、然后 push 两次当前枚举到的元素进入堆内

第一个 push 的意义是下次如果其作为堆顶元素、那么可以把它拿出来做减法达到反悔操作

第二个 push 的意义是下次拿出来的话就是真正的卖出去

 

 

代码:

#include <bits/stdc++.h>

using namespace std;

 

const double EPS = 1e-6;

const int INF = 0x3f3f3f3f;

const int mod = 1e9 + 7;

const int maxn = 1e5 + 10;

int n;

int a[maxn];

priority_queue<int, vector<int>, greater<int> > Q;

map<int, int> mp;

 

int main()

{

    int T;

    scanf("%d", &T);

    while(T--){

        scanf("%d", &n);

        for(int i = 0; i < n; i++) scanf("%d", &a[i]);

 

        while(!Q.empty()) Q.pop(); mp.clear();

 

        long long ans = 0, cnt = 0;

        for(int i = 0; i < n; i++){

            if(!Q.empty() && Q.top() < a[i]){

                int x = Q.top(); Q.pop();

                ans += a[i] - x; cnt++;

 

                if(mp[x]){ mp[x]--; cnt--;}

 

                Q.push(a[i]); mp[a[i]]++;

            }

            Q.push(a[i]);

        }

 

        printf("%lld %lld\n", ans, cnt << 1);

    }

 

    return 0;

}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值