【深基17.例5】木材仓库

题目

博艾市有一个木材仓库,里面可以存储各种长度的木材,但是保证没有两个木材的长度是相同的。作为仓库负责人,你有时候会进货,有时候会出货,因此需要维护这个库存。有不超过 100000 条的操作:

进货,格式1 Length:在仓库中放入一根长度为 Length(不超过 10^9 ) 的木材。如果已经有相同长度的木材那么输出Already Exist。

出货,格式2 Length:从仓库中取出长度为 Length 的木材。如果没有刚好长度的木材,取出仓库中存在的和要求长度最接近的木材。如果有多根木材符合要求,取出比较短的一根。输出取出的木材长度。如果仓库是空的,输出Empty。

输入输出样例

输入

7

1 1

1 5

1 3

2 3

2 3

2 3

2 3

输出

3

1

5

Empty

思路

用map来做

因为保证没有两个木材的长度是相同的,而且木头的长度最大已经到了10^9,不能用普通数组,可以用map来映射,map[a]就表示长度为a的木头是否存在

代码

#include<bits/stdc++.h>

using namespace std;

int n,a,b;

map <int,int> m; //m[b]表示长度为b的木材存不存在

int main()

{

scanf("%d",&n);

for (int i=1;i<=n;i++)

{

scanf("%d%d",&a,&b);

if (a==1) //存入木材

{

if (m.count(b)==false) m[b]=1; //存入长度为b的木材

else cout<<"Already Exist"<<endl; //长度为b的木材已经存在了,输出

}

else if (a==2) //取出木材

{

if (m.empty()==true) cout<<"Empty"<<endl; //仓库里一根木材也不剩了

else if (m.count(b)==true)//仓库里有刚好符合长度的木材

{

cout<<b<<endl; //直接输出长度b

m.erase(b); //不要忘记清楚已经取出的木材

}

else //要查找长度相近的木材了

{

m[b]=1; //假设长度为b的木头是存在的,把他放进仓库(方便寻找指针)

map <int,int>::iterator it1; //迭代器,it相当于指针

map <int,int>::iterator it2; //用两个指针,方便下面x与y的比较

it1=m.find(b); //it1现在指向长度为b的木材的指针

it2=it1;

it2++; //it2要++,表示b后面的木头

if (it1==m.begin()) //如果把长度为b的木头放进仓库后,b是长度最小的木头,就不用往左寻找比它短的木头了

{

cout<<(++it1)->first<<endl; //直接输出后面比它长一点的木头,因为木头长度是存在it->first中的,it->second存的是该木头是否存在

m.erase(it1); //毁尸灭迹(逃)

}

else if (it2==m.end()) //如果把长度为b的木头放进仓库后,b是长度最长的木头,就不用往右寻找比它长的木头了

//这里本人有个疑惑,这里的it2不是已经++了吗,就表示的是b后面的木头,可是如果b已经是最长的话,为什么不是it1(b的位置)是尾巴呢?望大佬指点

//我是看一位博主这样写的,如果这里是it1,就过不了

{

cout<<(--it1)->first<<endl; //直接输出前面比它短一点的木头

m.erase(it1); //毁尸灭迹(逃)

}

else

{

int x=b-((--it1)->first); //x等于b左边木头与b的长度差

int y=(it2->first)-b; //y等于b右边木头与b的长度差

if (x<=y) cout<<it1->first<<endl,m.erase(it1);//左边的木头更合适

else cout<<it2->first<<endl,m.erase(it2);//右边的木头更合适

}

m.erase(b); //别忘了把刚刚放进去的b给拿出来

}

}

}

return 0;

}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值