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

思路:维护一个递增队列,如果当天的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;
}

 

posted @ 2018-08-26 11:25  KirinSB  阅读(466)  评论(0编辑  收藏  举报