题目大意:
有
n
n
n件商品,价格为
P
1
,
P
2
,
.
.
.
,
P
n
P_1,P_2,...,P_n
P1,P2,...,Pn,有现金
M
M
M元,以及
k
k
k 张优惠券。对某件商品使用一张优惠券,价格会下降到
Q
i
Qi
Qi,每件商品有且只有一件,优惠券对每件商品至多使用一次。
分析:
我们先将降价后最小的
Q
1
,
Q
2
.
.
Q
k
Q_1,Q_2..Q_k
Q1,Q2..Qk全部累加,
然后可以利用优先队列建堆,
将
P
1
−
Q
1
,
P
2
−
Q
2
,
.
.
.
,
P
k
−
Q
k
P_1-Q_1,P_2-Q_2,...,P_k-Q_k
P1−Q1,P2−Q2,...,Pk−Qk建成一个小根堆
C
C
C,
将
P
k
+
1
,
P
k
+
2
,
.
.
.
,
P
n
P_{k+1},P_{k+2},...,P_n
Pk+1,Pk+2,...,Pn建成一个小根堆
A
A
A,
将
Q
k
+
1
,
Q
k
+
2
,
.
.
.
,
Q
n
Q_{k+1},Q_{k+2},...,Q_n
Qk+1,Qk+2,...,Qn建成一个小根堆
B
B
B,
每次找到2个合法的堆顶
A
t
o
p
,
B
t
o
p
A_{top},B_{top}
Atop,Btop,即商品没有被小
Y
Y
Y购买,以及
C
t
o
p
C_{top}
Ctop
然后判断直接购买
A
t
o
p
A_{top}
Atop,代价为
P
[
A
t
o
p
]
P[A_{top}]
P[Atop]
还是利用
C
t
o
p
C_{top}
Ctop撤销之前的优惠劵使用,然后购买商品
B
t
o
p
B_{top}
Btop,花费
P
[
C
t
o
p
]
−
Q
[
C
t
o
p
]
+
Q
[
B
t
o
p
]
P[C_{top}]-Q[C_{top}]+Q[B_top]
P[Ctop]−Q[Ctop]+Q[Btop]
然后注意一下维护,以及购买的合法性
代码:
#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdio>
#include<vector>
#include<cmath>
#include<queue>
#define N 50005
using namespace std;
typedef long long ll;
struct Node {
ll p, q;
int id;
friend bool operator < (Node aa, Node bb)
{
return aa.p > bb.p;
}
}a[N];
struct Code {
ll q, num;
int id;
friend bool operator < (Code aa, Code bb)
{
return aa.q > bb.q;
}
}b[N];
priority_queue <Node> Q1;
priority_queue <Code> Q2;
priority_queue <ll> Q3;
bool cmp(Node aa, Node bb)
{
return aa.q < bb.q;
}
int Check[N], n, k;
ll m;
int main()
{
scanf("%d %d %lld", &n, &k, &m);
for (int i = 1; i <= n; i++)
scanf("%lld %lld", &a[i].p, &a[i].q);
sort(a + 1, a + n + 1, cmp);
int cnt = 0;
for (int i = 1; i <= k; i++)
{
Q3.push(a[i].p - a[i].q);
m -= a[i].q;
if (m <= 0)
{
if (m == 0) ++cnt;
printf("%d\n", cnt);
return 0;
}
++cnt;
}
for (int i = k + 1; i <= n; i++)
{
b[i].q = a[i].q, b[i].num = a[i].p - a[i].q;
b[i].id = a[i].id = i;
Q1.push(a[i]);
Q2.push(b[i]);
}
while (m > 0)
{
while (Q1.size() && Check[Q1.top().id]) Q1.pop();
while (Q2.size() && Check[Q2.top().id]) Q2.pop();
if (Q1.size() == 0 && Q2.size() == 0) break;
if (Q1.size() == 0)
{
if (m - Q2.top().q - Q3.top() >= 0)
{
++cnt;
m -= (Q2.top().q + Q3.top());
Q3.pop();
Q3.push(Q2.top().num);
Check[Q2.top().id] = 1;
Q2.pop();
} else break;
} else
if (Q2.size() == 0)
{
if (m - Q1.top().p >= 0)
{
++cnt;
m -= Q1.top().p;
Check[Q1.top().id] = 1;
Q1.pop();
} else break;
} else
{
if (Q2.top().q + Q3.top() >= Q1.top().p)
{
if (m - Q1.top().p >= 0)
{
++cnt;
m -= Q1.top().p;
Check[Q1.top().id] = 1;
Q1.pop();
} else break;
} else
{
if (m - Q2.top().q - Q3.top() >= 0)
{
++cnt;
m -= (Q2.top().q + Q3.top());
Q3.pop();
Q3.push(Q2.top().num);
Check[Q2.top().id] = 1;
Q2.pop();
} else break;
}
}
}
printf("%d\n", cnt);
return 0;
}