lower_bound+set 木材仓库+烦恼的高考志愿

木材仓库

洛谷 P5250 木材仓库

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

  • 进货,格式1 Length:在仓库中放入一根长度为 Length(不超过 1 0 9 10^9 109 ) 的木材。如果已经有相同长度的木材那么输出Already Exist
  • 出货,格式2 Length:从仓库中取出长度为 Length 的木材。如果没有刚好长度的木材,取出仓库中存在的和要求长度最接近的木材。如果有多根木材符合要求,取出比较短的一根。输出取出的木材长度。如果仓库是空的,输出Empty

题目分析

此题考察的是set和lower_bound的使用,自己当时已经差不多忘记了有lower_bound这么一个东西
set里的几个方法在这里回顾一下

  • s.erase(value) ,在直接在容器中删除值为value的元素
  • lower_bound(value),查找出大于等于value的值的对应地址(指针)
#include <bits/stdc++.h>
using namespace std;

int main() {
	int m;
	scanf("%d", &m);
	set<int> s;

	while (m--) {
		int op, l;
		scanf("%d %d", &op, &l);
		if (op == 1) {
			int sz = s.size();
			s.insert(l);
			if (sz == s.size()) puts("Already Exist");
		} else if (op == 2) {
			if (s.size() == 0) { // 仓库为空
				puts("Empty");
				continue;
			}
			if (s.count(l)) { // 长度正好
				cout << l << endl;
				s.erase(l);
			}
			else { // 没有正好长度
				auto it = s.lower_bound(l); //选出大于等于l的木材
				int b = *it; 
				if (it != s.begin()) it--;
					
				int a = *it;
				if (abs(b-l) < abs(a-l)) {
					cout << b << endl;
					s.erase(b);
				} else {
					cout << a << endl;
					s.erase(a);
				}
			}
		}
	} 
	
	return 0;
}

烦恼的高考志愿

P1678 烦恼的高考志愿原题链接
直接调用set中的lower_bound函数,找到大于等于考试分的院校分数线。
再it–,取到它的前一位。两者对比求最小值

STL

#include <bits/stdc++.h>
using namespace std;
const int N = 1e5 + 10;
int m, n;
set<int> s;

int main() {
	cin >> m >> n;
	for (int i = 0; i < m; i++) {
		int x;
		scanf("%d", &x);
		s.insert(x);
	}
	
	int ans = 0;
	while(n--) {
		int score;
		scanf("%d", &score);
		auto it = s.lower_bound(score);
		int b = *it;
		if (it != s.begin()) it--;
		int a = *it;
		int temp = abs(b-score) < abs(a-score) ? abs(b-score):abs(a-score);
		ans += temp;
	}
	cout << ans;
	
	return 0;
}

二分

如果不记得STL,就无法做了吗???
STL只是工具,也是人实现的,就拿lower_bound来说,本质就是二分
自己在考场上仍然需要静下心来,戒骄戒躁

#include <bits/stdc++.h>
using namespace std;
const int N = 1e5 + 10;
int m, n;
int s[N];

int main() {
	cin >> m >> n;
	for (int i = 0; i < m; i++) 
		scanf("%d", &s[i]);
	sort(s, s+m);
	
	int ans = 0;
	while(n--) {
		int score;
		scanf("%d", &score);
		
		int l = 0, r = m;
		int temp = 1e9;
		while(l < r) {
			int mid = l + r >> 1;
			if (s[mid] >= score) {
				r = mid;
				temp = min(temp, abs(s[mid] - score));
			} else l = mid + 1;
		}
		if (score > s[m-1]) temp = abs(score - s[m-1]);
		if (score < s[0]) temp = abs(s[0] - score);
		if (r > 0)
		temp = min(temp, abs(s[r-1] - score));
		ans+= temp;
	}
	cout << ans;
	
	return 0;
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

CodeSlogan

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值