购物

时间:2021-08-26
本文章向大家介绍购物,主要包括购物使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。

题目大意

\(n\) 件商品,每一件商品价格为 \(P_i\) 个单位。

现在你手中共有 \(m\) 个单位的现金,以及 \(k\) 张优惠券。

你可以在购买某件商品时,使用至多一张优惠券,若如此做,该商品的价格会下降至 \(Q_i\)

请问你至多能购买多少件商品。

解题思路

考虑贪心,先不考虑有没有优惠卷的情况肯定是从小到大买,这样一定会买的最多的。

按照这个思想,每一次买的时候就找最小的。

有两种情况:

  • 使用了优惠券之后获得了一个最小值。
  • 没有使用优惠券的最小值。

分别对 \(p\)\(q\) 进行排序。

每次找最小的。

还要将用来优惠券的那些东西按照 \(p_i − q_i\) 放到堆里面,为以后撤销优惠券使用。

这就是反悔贪心。

AC CODE

#include <cstdio>
#include <queue>
#include <algorithm>
using namespace std;
#define int long long
 
const int maxn = 1e6 + 5;
 
struct node
{
    int p, q;
    bool operator < (const node& rhs) const
    {
        return p - q > rhs.p - rhs.q;
    }
} a[maxn];
 
int n, k, ans;
long long m;
priority_queue<node> Q;
 
bool cmp(node a, node b)
{
    if(a.q != b.q)
        return a.q < b.q;
    return a.p < b.p;
}
 
bool CMP(node a, node b)
{
    return a.p < b.p;
}
 
signed main()
{
    scanf("%lld%lld%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);
    for (int i = 1; i <= k; i++)
    {
        m -= a[i].q;
        Q.push(a[i]);
        if (m < 0)
        {
            printf("%lld\n", i - 1);
            return 0;
        }
    }
    ans = k;
    sort(a + k + 1, a + n + 1, CMP);
    for (int i = k + 1; i <= n; i++)
    {
        int tp = Q.top().p, tq = Q.top().q;
        if (a[i].p - a[i].q > tp - tq && a[i].q + tp - tq <= m)
        {
            m -= (a[i].q + tp - tq);
            ans++, Q.pop(), Q.push(a[i]);
        }
        else if (a[i].p <= m)
            ans++, m -= a[i].p;
    }
    printf("%lld\n", ans);
    return 0;
}

本文来自博客园,作者:蒟蒻orz,转载请注明原文链接:https://www.cnblogs.com/orzz/p/15191687.html

原文地址:https://www.cnblogs.com/orzz/p/15191687.html