洛谷-set and map-P5250-【深基17.例5】木材仓库

【深基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;
}
  • 3
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值