0x17二叉堆之超市

题目链接:https://www.acwing.com/problem/content/147/

容易想到一个贪心策略:在最优解中,对于每个时间(天数) t,应该在保证不卖出过期商品的前提下,尽量卖出利润前t大的商品。因此,我们可以依次考虑每个商品,动态维护一个满足上述性质的方案。
详细地说,我们把商品按照过期时间排序,建立一个初始为空的小根堆 (节点权值为商品利润),然后扫描每个商品:
1.若当前商品的过期时间(天数) t等于当前堆中的商品个数,则说明在目前方案下,前t天已经安排了t个商品卖出。此时,若当前商品的利润大于堆顶权值(即已经安排的t个商品中的最低利润),则替换掉堆顶(用当前商品替换掉原方案中利润最低的商品)。

2.若当前商品的过期时间(天数)大于当前堆中的商品个数,直接把该商品插入堆。

3.若当前商品的过期时间(天数)小于当前堆中商品的个数,哦!!!不可能,因为在第一种情况中,若当前商品的过期时间(天数) t等于当前堆中的商品个数,我们就会替换掉商品。
最终,堆里的所有商品就是我们需要卖出的商品,它们的利润之和就是答案。该算法的时间复杂度为O(N logN)。

#include<iostream>
#include<vector>
#include<algorithm>
#include<queue>
using namespace std;
struct node{
    int val;
    int time;

}nodes[10050];
bool operator <(const node &a, const node &b) {
    return a.time<b.time;
}
int main(){
    int n;
    while (cin>>n) {
        for (int i = 1; i <= n; ++i) {
            cin>>nodes[i].val>>nodes[i].time;
        }
        sort(nodes+1,nodes+n+1);

        priority_queue<int,vector<int>, greater<int> > q;
        for (int i = 1 ; i <=n; ++i) {
            int currentDay=nodes[i].time;
            if (currentDay>q.size()) {
                q.push(nodes[i].val);
            }else {
                int vals=q.top();
                if(vals<nodes[i].val){
                    q.pop();
                    q.push(nodes[i].val);
                }
            }
        }
        int ans=0;
        while (!q.empty()) {
            ans+=q.top();
            q.pop();
        }
        cout<<ans<<endl;
    }
    return 0;
}

  

加油啦!加油鸭,冲鸭!!!
原文地址:https://www.cnblogs.com/clarencezzh/p/10793474.html