[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;
}