FJ看中了N(1 <= N <= 50,000)头牛,他有m (1 <= M <= 10^14)元,还有k(1 <= K <= N)张优惠券。
第i头牛的价格为P_i (1 <= P_i <= 10^9),如果使用优惠券则为C_i (1 <= C_i <= P_i)。问农夫最多能买到多少头牛。
Input
* 行1: 三个整数: N, K, and M.
* 行2..N+1: 每行两个整数 P_i 和 C_i.
Output
一个整数为买到牛数量
Sample Input
4 1 7
3 2
2 2
8 1
4 3
Sample Output
3
样例说明:
将优惠卷用在第三头牛身上,付出1元,再买前两头牛付出3+2=6元,共支出7元,买到3头牛
Sol:
可以认为买每头牛都用到了优惠卷,只是最开始的优惠卷支出是0元,后面的就要付出代价了。所以我们在买牛时,如果是原价买自然要买最便宜的,如果是用优惠价来买,也是买最便宜的,当然此时要用到优惠券,优惠券自然也要用最便宜的了.所以对于每次购买讨论下看是直接买,还是优惠价+优惠券哪种更便宜,当然这两种方式可能买得并不是同一种物品哟。
#include<queue> #include<cstdio> #include<algorithm> using namespace std; struct node { int num, id; }; bool operator < (node x, node y) { return x.num > y.num; } priority_queue<node> q1, q2; //重载运算符后成为小根堆 priority_queue<int, vector<int>, greater<int> > q3; //定义一个小根堆 int N, K, ans; long long M; int use[150001], p[150001], q[150001]; int main() { scanf("%d %d %lld", &N, &K, &M); //N个物品,k张优惠卷,M元钱 for (int i = 1; i <= N; i++) { scanf("%d %d", &p[i], &q[i]); q1.push((node){p[i], i});//放原价 q2.push((node){q[i], i});//放优惠价 } for (int i = 1; i <= K; i++) q3.push(0);//一开始有k张优惠券,价格为0 for (; M > 0 && ans < N; ) { while (use[q1.top().id]) q1.pop(); while (use[q2.top().id]) q2.pop(); if (q1.top().num <= q2.top().num + q3.top()) {//q1这个堆中放的是如果直接买的话,最便宜的 //q2放的是如果使用优惠券的话,最便宜的 //对于优惠券我们可以认为开始价格为0,如果如果要赎回的话,自然也是赎回代价最小的 node x = q1.top(); M -= x.num; if (M < 0) break; use[x.id] = 1; q1.pop(); ans++; } else {//花券买 node x = q2.top(); M -= x.num + q3.top(); if (M < 0) break; use[x.id] = 1; q3.pop(); q3.push(p[x.id] - q[x.id]); //新放入这个物品可撤回的优惠券 q2.pop(); ans++; } } printf("%d", ans); }
BZOJ2590 [Usaco2012 Feb] Cow Coupons
原文:https://www.cnblogs.com/cutemush/p/11679965.html