set和map的左右护卫【刷题反思】
- 电脑硬件
- 2025-09-20 05:24:01

1. 相近的营业额 1.1 题目
题目描述:我们定义,一天营业额的最小波动 = min { | 该天以前某一天的营业额 - 该天营业额 | }
特别的,第一天的营业额最小波动为第一天的营业额
输入描述:第一行 n (n <= 32767),表示公司从成立到现在的天数
接下来 n 行每行有一个整数 ai (|ai| <= 10e6),表示第 i 天的营业额,可能存在负数
输出描述:一个正整数,表示每一天最小波动的和,保证结果小于 2^31
输入:
6
5
1
2
5
4
6
输出:
12
1.2 思想对于每一个新的数 x ,我们总共要找到距离 x 最近的一大一小的两个数,可以将之前的数据放入到 set 中,对于大于等于 x 的值可以用 lower_bound 得到 set 中该值的迭代器,让迭代器进行(--)操作,可以得到比 x 小的最接近 x 的值,然后让各自与 x 的差值进行比较就可以得到最小波动值
值得注意的是:当对迭代器进行(--)操作时,如果 set 里的元素不够,可能非法访问,所以我们需要左右护法进行保护,而左右护法也不能干涉比较的结果,那左右护法可以趋于无穷(即这个情况下不可能取到的值)
1.3 模拟实现 #include<iostream> using namespace std; #include<set> #include<cmath> set<int> mp; //注意近似无穷的值 int INF = 1e7+10; int total; int main() { int n; cin >> n; int x; cin >> x; //先将第一天的值插入 mp.insert(x); total += x; //添加左右护法 mp.insert(INF); mp.insert(-INF); for(int i=2;i<=n;i++) { int x; cin >> x; //取出大于等于 x 的值的迭代器 auto it1 = mp.lower_bound(x); //找到最近的小于 x 的迭代器 auto it2 = it1; it2--; //进行比较 total += min(abs( *it1 - x ), abs( *it2 - x )); //最后将今天的 x 插入 mp.insert(x); } cout << total << endl; return 0; } 2. 相近的木材 2.1 题目题目描述:有一个木材仓库,里面没有两个木材的长度相同,现在有不超过100000条操作:
进货格式:1 length:向仓库中放入长度为 length (不超过 10e9)的木材,如果已经存在,就输出 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 2.2 思想和上面的解法类似,对于要删除的数 x ,我们总共要找到距离 x 最近的一大一小的两个数,可以将之前的数据放入到 set 中,对于大于等于 x 的值可以用 lower_bound 得到 set 中该值的迭代器,让迭代器进行(--)操作,可以得到比 x 小的最接近 x 的值,然后让各自与 x 的差值进行比较就可以得到要删除的值
值得注意的是:当对迭代器进行(--)操作时,如果 set 里的元素不够,可能非法访问,所以我们需要左右护法进行保护,而左右护法也不能干涉比较的结果,那左右护法可以趋于无穷(即这个情况下不可能取到的值)
2.3 模拟实现 #include<iostream> using namespace std; #include<set> #include<cmath> typedef long long LL; //注意元素的范围 set<LL> mp; //左右护法,该情况下可以看作趋于无穷 LL INF = 1e10 + 10; int main() { int n; cin >> n; while (n--) { LL op, x; cin >> op >> x; //添加左右护法 mp.insert(INF); mp.insert(-INF); if (op == 1) { //如果 set 没有就插入 if (mp.count(x)) cout << "Already Exist" << endl; else mp.insert(x); } else { //只有左右护法可以将 set 看作空 if (mp.size() == 2) cout << "Empty" << endl; else { //取出大于等于 x 的值的迭代器 auto it1 = mp.lower_bound(x); //找到最近的小于 x 的迭代器 auto it2 = it1; it2--; //进行比较 if (abs(*it1 - x) >= abs(*it2 - x)) { cout << *it2 << endl; mp.erase(*it2); } else { cout << *it1 << endl; mp.erase(*it1); } } } } return 0; }set和map的左右护卫【刷题反思】由讯客互联电脑硬件栏目发布,感谢您对讯客互联的认可,以及对我们原创作品以及文章的青睐,非常欢迎各位朋友分享到个人网站或者朋友圈,但转载请说明文章出处“set和map的左右护卫【刷题反思】”