Codeforces Round #413 B. T-shirt buying

本文介绍了一种利用优先队列解决特定购物场景问题的方法。面对n件具有不同颜色及价格的T恤和m位顾客,每位顾客都有自己的偏好颜色。通过使用优先队列来跟踪最便宜的T恤,确保每位顾客都能购买到至少一面符合其偏好的最低价T恤。文章详细解释了解题思路并提供了完整的代码实现。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

A new pack of n t-shirts came to a shop. Each of the t-shirts is characterized by three integers pi, ai and bi, where pi is the price of the i-th t-shirt, ai is front color of the i-th t-shirt and bi is back color of the i-th t-shirt. All values pi are distinct, and values ai and bi are integers from 1 to 3.

m buyers will come to the shop. Each of them wants to buy exactly one t-shirt. For the j-th buyer we know his favorite color cj.

A buyer agrees to buy a t-shirt, if at least one side (front or back) is painted in his favorite color. Among all t-shirts that have colors acceptable to this buyer he will choose the cheapest one. If there are no such t-shirts, the buyer won’t buy anything. Assume that the buyers come one by one, and each buyer is served only after the previous one is served.

You are to compute the prices each buyer will pay for t-shirts.

题意

有 n 件T恤,每件正面与反面的颜色均为 1-3 中一种(可能相同),每件的价格为 pi ,且均不同。m 个顾客依次前来买一件衣服,对于第 j 个顾客,他所选择的衣服一定存在至少一面是他喜欢的颜色 cj ,且将选择所有符合条件的衣服中最便宜的一件。输出 m 个顾客所消费的金额?若没有满足条件的衣服,则不买,输出 -1 。

解题思路

对颜色 1, 2, 3 分别建立优先队列,价格小的靠近队首。若每件衣服只属于一个队列,则对每个顾客抛出队首元素即可。但衣服具有正反两面,即每件衣服可能分属两个不同的优先队列,故为解决这种情况,应设置标记数组,记录该件衣服是否已经出售。

代码

#include<bits/stdc++.h>
using namespace std;
const int N = 200000 + 10;
struct T_SHIRT {
    int p, a, b, id;
} t[N], tmp;
bool operator<(T_SHIRT a, T_SHIRT b) {
    return a.p > b.p;
}
bool mrk[N];
priority_queue<T_SHIRT> que[4];
int main()
{
    int n, m;
    scanf("%d", &n);
    for(int i=1;i<=n;i++)
        scanf("%d",&t[i].p);
    for(int i=1;i<=n;i++)
        scanf("%d",&t[i].a);
    for(int i=1;i<=n;i++)
        scanf("%d",&t[i].b);
    for(int i=1;i<=n;i++) {
        t[i].id = i;
        que[t[i].a].push(t[i]);
        if(t[i].a != t[i].b)    que[t[i].b].push(t[i]);
    }
    scanf("%d",&m);
    for(int i=1, c;i<=m;i++)
    {
        scanf("%d",&c);
        if(que[c].empty())  printf("-1 ");
        while(!que[c].empty())
        {
            tmp = que[c].top();
            que[c].pop();
            if(mrk[tmp.id]) {
                if(que[c].empty())  printf("-1 ");
                continue;
            }
            mrk[tmp.id] = 1;
            printf("%d ", tmp.p);
            break;
        }
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值