1. 程式人生 > >【可撤銷貪心 堆】SSL_1148 購物

【可撤銷貪心 堆】SSL_1148 購物

題意

給出NN件商品,KK張優惠券,每個商品原價為pip_i,使用優惠券後價格為qiq_i,現在有MM錢,求出最多能買多少件商品。

思路

33個小根堆,分別放pip_iqiq_ipiqip_i-q_i,其中piqip_i-q_i相當於再花那麼多錢就可以得到一張優惠券(可撤銷)。每次我們比較一下是直接買優惠還是買優惠券再買優惠。

程式碼

#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); 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張優惠券 for (; M > 0 && ans < N; ans++) { while (use[q1.top().id]) q1.pop(); while (use[q2.
top().id]) q2.pop(); if (q1.top().num <= q2.top().num + q3.top()) {//直接買 node x = q1.top(); M -= x.num; if (M < 0) break; use[x.id] = 1; q1.pop(); } 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(); } } printf("%d", ans); }