【深基17.例5】木材仓库
题目描述
博艾市有一个木材仓库,里面可以存储各种长度的木材,但是保证没有两个木材的长度是相同的。作为仓库负责人,你有时候会进货,有时候会出货,因此需要维护这个库存。有不超过 100000 条的操作:
- 进货,格式
1 Length
:在仓库中放入一根长度为 Length(不超过 1 0 9 10^9 109) 的木材。如果已经有相同长度的木材那么输出Already Exist
。 - 出货,格式
2 Length
:从仓库中取出长度为 Length 的木材。如果没有刚好长度的木材,取出仓库中存在的和要求长度最接近的木材。如果有多根木材符合要求,取出比较短的一根。输出取出的木材长度。如果仓库是空的,输出Empty
。
输入格式
输出格式
样例 #1
样例输入 #1
7
1 1
1 5
1 3
2 3
2 3
2 3
2 3
样例输出 #1
3
1
5
Empty
思路
首先进货比较简单,我们只需要判断set中是否有该长度的木材,没有的话直接插入即可。
其次主要是如何出货,出货主要分4部分,
1:有length的木材直接出货。
2:没有length长度的木材取最接近的木材出货。
3:有多个接近的木材取最小的一个。
4:什么都没有输出空。
我们一个一个分析
1:第一步和第四步比较简单我们可以直接判断,先判断set是不是空,再find找有没有length。
2:没有length我们就需要找到最接近的木材。首先前提我们知道map的key是自动排序的。所以我们可以利用 upper_bound函数先找到第一个别 length 大的数 itup 表示,然后比较length前的较小的数 it 来表示,也就是 it < length < itup,但是其实length此时是没有的 ,就是 it < itup;我们只需要比 length - it 和 itup - length 的大小,就能找到最接近的木材。
代码
#include<bits/stdc++.h>
using namespace std;
int main(){
int n;
cin>>n;
set<int> a;
set<int>::iterator it,itup;//这里的it和itup是迭代器用来记录在set中的位置,和刚才思路中的it和itup是不同的。
for(int i=0;i<n;i++){
int type,length;
cin>>type>>length;
it=find(a.begin(),a.end(),length);//it来找是否有length
if(type==1){//进货
if(it==a.end()) a.insert(length);
else
cout<<"Already Exist"<<endl;
}
else if(type==2){//出货
if(a.empty()) cout<<"Empty"<<endl;//空
else if(it!=a.end()){//找到length的木材
cout<<length<<endl;
a.erase(it);
}
else{//没有length的木材
itup=upper_bound(a.begin(),a.end(),length);
//两种特殊情况 1,没有找到比length大的木材,也就是说length是最大的,那么就输出目前最大的那个木材。2,length 最小,直接输出当前最小的木材。
//情况1
if(itup==a.end()){
itup--;//因为upper_bound 函数从数组的begin位置到end-1位置二分查找第一个大于num的数字,找到返回该数字的地址,不存在则返回end。
cout<<*itup<<endl;
a.erase(itup);
}
//情况2
else if(itup==a.begin()){
cout<<*itup<<endl;
a.erase(itup);
} else{
itup--;
it=itup++;
if(length - *it <= *itup - length){
cout<<*it<<endl;
a.erase(it);
}
else{
cout<<*itup<<endl;
a.erase(itup);
}
}
}
}
}
return 0;
}