HDU 6438 网络赛 Buy and Resell(贪心 + 优先队列)题解

博客介绍了一种求最大收益的算法思路,通过维护递增队列,若当天的w比队首大,给收益增加w - q.top()。w可能作为中间价/最终卖出价或买入价,会入队两次。还提到用map[i]计算总数,最后给出参考及代码来源。

思路:维护一个递增队列,如果当天的w比队首大,那么我们给收益增加 w - q.top(),这里的意思可以理解为w对总收益的贡献而不是真正获利的具体数额,这样我们就能求出最大收益。注意一下,如果w对收益有贡献,你会发现w入队了两次,这是因为这里的w可能会有两种可能:

1.当做中间价/最终卖出价

2.买入价

所以我们入队两个w,如果w是买入价,那么其中一个w作为中间价势必弹出,另一个w作为买入价;如果w是最终卖出价,那么两个w会一直待在队列里。

计算总数很简单,用map[i]表示以i为中间价还存在多少个,如果是中间价就不加数量。

记得开long long orz

参考:CodeForces - 867E Buy Low Sell High 贪心 + 优先队列

代码:

#include<cstdio>
#include<queue>
#include<map>
#include<algorithm>
#include<iostream>
#define ll long long
using namespace std;
priority_queue<int, vector<int>, greater<int> > q;
map<int, int> st;
int main(){
    int T, n, w;
    scanf("%d", &T);
    while(T--){
        st.clear();
        while(!q.empty()) q.pop();
        scanf("%d", &n);
        ll num = 0, ans = 0;
        for(int i = 0; i < n; i++){
            scanf("%d", &w);
            if(!q.empty() && q.top() < w){
                if(st[q.top()] > 0){
                    st[q.top()]--;
                }
                else{
                    num += 2;
                }
                st[w]++;
                ans += w - q.top();
                q.pop();
                q.push(w);
            }
            q.push(w);
        }
        printf("%lld %lld\n",ans, num);
    }
    return 0;
}

 

转载于:https://www.cnblogs.com/KirinSB/p/9536670.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值