BZOJ 2802 Poi2012 Warehouse Store 堆+贪心

题目大意:有n天,早上进货中午卖,可以选择卖或者不卖,问最多可以卖出多少人

首先贪心的思想是如果当前能卖就卖

但是这样不一定是最优的

比如说我第一天来一个人把所有的库存都买走了 然后后面基本没有补给 后面的人都饿死了

因此我们维护一个大根堆来记录我们都卖出了多少份

如果有一个人买不到 我们去大根堆里寻找有没有买的比他多的 如果有 把之前的人取消 卖给这个人

这样虽然不能增加答案 但是可以增加库存

#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#define M 250100
using namespace std;
typedef pair<int,int> abcd;
int n,a[M],b[M],ans[M];
long long stock;
namespace Priority_Heap{
	abcd heap[M];int top;
	void Insert(abcd x)
	{
		heap[++top]=x;
		int t=top;
		while(t>1)
		{
			if(heap[t]>heap[t>>1])
				swap(heap[t],heap[t>>1]),t>>=1;
			else
				break;
		}
	}
	void Pop()
	{
		heap[1]=heap[top--];
		int t=2;
		while(t<=top)
		{
			if(t<top&&heap[t+1]>heap[t])
				++t;
			if(heap[t]>heap[t>>1])
				swap(heap[t],heap[t>>1]),t<<=1;
			else
				break;
		}
	}
}
int main()
{
	int i;
	cin>>n;
	for(i=1;i<=n;i++)
		scanf("%d",&a[i]);
	for(i=1;i<=n;i++)
		scanf("%d",&b[i]);
	for(i=1;i<=n;i++)
	{
		stock+=a[i];
		if(stock>=b[i])
			stock-=b[i],Priority_Heap::Insert(abcd(b[i],i));
		else
		{
			if(Priority_Heap::heap[1].first<b[i])
				continue;
			stock+=Priority_Heap::heap[1].first;
			stock-=b[i];
			Priority_Heap::Pop();
			Priority_Heap::Insert(abcd(b[i],i));
		}
	}
	cout<<Priority_Heap::top<<endl;
	for(i=1;i<=Priority_Heap::top;i++)
		ans[++ans[0]]=Priority_Heap::heap[i].second;
	sort(ans+1,ans+ans[0]+1);
	for(i=1;i<=ans[0];i++)
		printf("%d%c",ans[i],i==ans[0]?'\n':' ');
	return 0;
}
时间: 2024-08-15 10:06:31

BZOJ 2802 Poi2012 Warehouse Store 堆+贪心的相关文章

bzoj 2802: [Poi2012]Warehouse Store 题解

[原题] 2802: [Poi2012]Warehouse Store Time Limit: 10 Sec  Memory Limit: 64 MBSec  Special Judge Submit: 94  Solved: 54 Description 有一家专卖一种商品的店,考虑连续的n天. 第i天上午会进货Ai件商品,中午的时候会有顾客需要购买Bi件商品,可以选择满足顾客的要求,或是无视掉他. 如果要满足顾客的需求,就必须要有足够的库存.问最多能够满足多少个顾客的需求. Input 第一

【BZOJ】2802: [Poi2012]Warehouse Store(贪心)

http://www.lydsy.com/JudgeOnline/problem.php?id=2802 自己yy了一下... 每一次如果够那么就买. 如果不够,考虑之前买过的,如果之前买过的比当前花费的钱多,那么就去掉之前买的,变成买现在的. 如何证明?不知道QAQ 还有...注意开longlong... #include <cstdio> #include <cstring> #include <cmath> #include <string> #inc

BZOJ2802 [Poi2012]Warehouse Store

恩...贪心来着... 我们先贪心当天能不能满足客户要求,如果能就尽量满足. 好了现在不能满足怎么办?作为一个无良的商家,可以退掉以前的订单...(现实中真的可以?...) 为了让当前剩余货物总量尽可能大,当然是退掉之前要求最高的订单喽,于是用堆维护一下就好了 注意long long什么的就好了 1 /************************************************************** 2 Problem: 2802 3 User: rausen 4 La

BZOJ 1029: [JSOI2007]建筑抢修 堆+贪心

1029: [JSOI2007]建筑抢修 Description 小刚在玩JSOI提供的一个称之为“建筑抢修”的电脑游戏:经过了一场激烈的战斗,T部落消灭了所有z部落的入侵者.但是T部落的基地里已经有N个建筑设施受到了严重的损伤,如果不尽快修复的话,这些建筑设施将会完全毁坏.现在的情况是:T部落基地里只有一个修理工人,虽然他能瞬间到达任何一个建筑,但是修复每个建筑都需要一定的时间.同时,修理工人修理完一个建筑才能修理下一个建筑,不能同时修理多个建筑.如果某个建筑在一段时间之内没有完全修理完毕,这

BZOJ 1528 POI2005 sam-Toy Cars 堆+贪心

题目大意:有n个玩具,都放在架子上,地板上能放k个,要玩p次玩具,如果不在地板上就要去架子上拿,地板满了要放回去,求最少操作次数 贪心思想:每次放回玩具时选择下次玩的时间最靠后的玩具放回去 可以用堆来模拟这一贪心过程 #include <cstdio> #include <cstring> #include <iostream> #include <algorithm> #define M 500500 using namespace std; typede

BZOJ 1150--数据备份(链表&amp;堆&amp;贪心)

1150: [CTSC2007]数据备份Backup Time Limit: 10 Sec  Memory Limit: 162 MBSubmit: 2572  Solved: 1038[Submit][Status][Discuss] Description 你在一家 IT 公司为大型写字楼或办公楼(offices)的计算机数据做备份.然而数据备份的工作是枯燥乏味的,因此你想设计一个系统让不同的办公楼彼此之间互相备份,而你则坐在家中尽享计算机游戏的乐趣.已知办公楼都位于同一条街上.你决定给这些

BNUOJ 34025 -Poor Warehouse Keeper(贪心)

题目:BNUOJ 34025 -Poor Warehouse Keeper(贪心) 题目大意:有一个商品的信息表,上面是数量,下面是总价,然后旁边各有一个按钮.上面的数量按钮按一下数量就加1,然后价格对应的也要在加上一个当前的单价.下面的按钮按一下的话,就对应的总价加1.初始状态是 1 1,然后给出终点状态,问能否得到.可以的话输出最少要按几次按钮,否则输出-1:总价每次输出都是下取整. 解题思路:如果想要尽快的得到总点状态的值,那么就应该按总价的按钮,因为只有总价变大了,商品对因的单价就上升了

POJ3253 Fence Repair 小顶堆+贪心

给了你N个木棒,求把他们组装成一根需要的最小花费,每次只能选两根组装在一起,需要的花费为两个木棒之和, 以前遇到过把一整根切开的,那个是DP,这个则有些类似,可是大胆的猜测了一下,直接每次选取所有木棒中最短的两根,这样就可以了,那么贪心是适用的,但是数量很多,而且两根最短的组装好了得插回去,这样不可能每次都排序吧, 这题首先优先队列肯定是可以做的, 最小堆也是可以的,每次都选出堆里的最小的两个求和再放回去即可 队列本身也就是堆吧,所以差别不大,但是没用过最小堆最大堆的 所以用一次把 #inclu

P4053 [JSOI2007]建筑抢修 堆贪心

思路:堆贪心 提交:1次 题解: 先按时间\(sort\),然后如果能修就直接扔堆里,不能修取堆顶比一下时间长短,把时间短的扔进堆: #include<cstdio> #include<iostream> #include<queue> #include<algorithm> #define ull unsigned long long #define ll long long #define R register int using namespace s