[USACO12FEB]Cow Coupons G

题目链接

这个数据范围想不到dp
考虑贪心一下

一开始想把所有的C和P按到优先队列里一个个取出来
过了14/15的数据点把我吓了一跳

最后一个数据点直接把我卡死

2 1 5
2 3
1 1000

一开始按C排个序,前K个必然是要选的
因为他们的下限最小

对于剩下的无非两种选择,P买,C买
P买就直接算
按C买就要进行贪心的反悔,考虑维护一个用了优惠券的P-C的优先队列
进行更换
两者最优的一个进行操作

#include <iostream>
#include <algorithm>
#include <queue>
using namespace std;
#define MAXN 200005

int N,K;
long long M;

struct Node {
    long long P,C;
} A[MAXN];

inline bool cmp(Node x,Node y) {
    return x.C < y.C;
}

struct node1 {
    long long ans;
    inline bool operator < (const node1& x) const {
        return ans > x.ans;
    }
};

priority_queue <node1> ans;

struct node2 {
    long long P,C;
    inline bool operator < (const node2& x) const {
        return P > x.P;
    }
};

priority_queue <node2> q;

int main() {

    ios::sync_with_stdio(0);
    cin.tie(0); cout.tie(0);

    cin >> N >> K >> M;
    for(int i=1;i<=N;++i) {
        cin >> A[i].P >> A[i].C;
    }

    int cnt = 0; int i;
    sort(A+1,A+N+1,cmp);
    for(i=1;i<=K;++i) {
        if(M>A[i].C) {
            M -= A[i].C; ans.push((node1){-A[i].C+A[i].P});
            cnt++;
        }
    }

    if(cnt==0) {
        cout << cnt; return 0;
    }

    for(int j=K+1;j<=N;++j) {
        q.push((node2){A[j].P,A[j].C});
    }    


    while(!q.empty()) {
        long long P = q.top().P,C = q.top().C; q.pop();
        long long temp = C + ans.top().ans;
        if(P<=temp) {
            if(M>=P) {
                M -= P; cnt ++; 
            }
        }
        else {
            if(M>=temp) {
                M -= temp; ans.pop(); cnt ++;
                ans.push((node1){P-C});
            }
        }
    }

    cout << cnt;
    return 0;
}
posted @ 2021-10-23 17:45  Neworld1111  阅读(48)  评论(0编辑  收藏  举报