Jzoj P5461 购物___优先队列

13 篇文章 0 订阅

题目大意:

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 P1Q1,P2Q2,...,PkQk建成一个小根堆 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;
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
提供的源码资源涵盖了Java应用等多个领域,每个领域都包含了丰富的实例和项目。这些源码都是基于各自平台的最新技术和标准编写,确保了在对应环境下能够无缝运行。同时,源码中配备了详细的注释和文档,帮助用户快速理解代码结构和实现逻辑。 适用人群: 适合毕业设计、课程设计作业。这些源码资源特别适合大学生群体。无论你是计算机相关专业的学生,还是对其他领域编程感兴趣的学生,这些资源都能为你提供宝贵的学习和实践机会。通过学习和运行这些源码,你可以掌握各平台开发的基础知识,提升编程能力和项目实战经验。 使用场景及目标: 在学习阶段,你可以利用这些源码资源进行课程实践、课外项目或毕业设计。通过分析和运行源码,你将深入了解各平台开发的技术细节和最佳实践,逐步培养起自己的项目开发和问题解决能力。此外,在求职或创业过程中,具备跨平台开发能力的大学生将更具竞争力。 其他说明: 为了确保源码资源的可运行性和易用性,特别注意了以下几点:首先,每份源码都提供了详细的运行环境和依赖说明,确保用户能够轻松搭建起开发环境;其次,源码中的注释和文档都非常完善,方便用户快速上手和理解代码;最后,我会定期更新这些源码资源,以适应各平台技术的最新发展和市场需求。 所有源码均经过严格测试,可以直接运行,可以放心下载使用。有任何使用问题欢迎随时与博主沟通,第一时间进行解答!

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值