STL函数 lower_bound 和 upper_bound 在算法竞赛中的用法
以前比较排斥这两个函数,遇到需要二分的情景都是手写 \(while(left<=right)\)。
这次决定洗心革面记录一下这两个函数的在算法竞赛中的用法,毕竟一般不会导致TLE。

其实百度百科已经概述得比较清楚了,
我们假设 \(value\) 为一个给定的数值,
\(lower\_bound\) 是在一个升序序列中从前后后找第一个大于等于 \(value\) 的值,
\(upper\_bound\) 是在一个升序序列中从前后后找第一个大于 \(value\) 的值。
比如:\(lower\_bound(a+1,a+n+1,k)\) 就是在\(a\)数组的\([1,n]\)范围(必须升序)里从前到后找第一个大于等于\(k\)的值,并以指针的形式返回。
注意,这两个函数的返回值都是一个指针,指向原序列中可以插入value,而不会破坏容器顺序的第一个位置。
我们可以在指针函数前面加个取值符 * ,来获得想得到的值。
看到这里,你应该知道lower和upper这两个单词的含义的吧,即将value插入某位置后该序列仍然分别是单调不严格递增和单调严格递增的。
举个栗子:
int *p1,*p2;
int a[6]={3,5,6,6,7,9};
p1=lower_bound(a,a+6,6);
p2=upper_bound(a,a+6,6);
printf("内存地址: p1 -> %d p2 -> %d\n",p1,p2);
printf("在原序列中找到的值: p1 = %d p2 = %d\n",*p1,*p2);
运行结果为:
内存地址: p1 -> 7339512 p2 -> 7339520
在原序列中找到的值: p1 = 6 p2 = 7
如果我们不想使用指针操作也可以,可以这样写: \(lower\_bound(a+1,a+n+1,k) - a\)
意思是把找出的指针地址减去a数组的起始内存地址(数组的内存是连续的),获得该值的位置在a数组中的下标。
int p1,p2;
int a[6]={3,5,6,6,7,9};
p1=lower_bound(a,a+6,6)-a;
p2=upper_bound(a,a+6,6)-a;
printf("找出的值的下标: p1 = %d p2 = %d\n",p1,p2);
printf("找出的值: a[%d] = %d a[%d] = %d\n",p1,a[p1],p2,a[p2]);
运行结果为:
找出的值的下标: p1 = 2 p2 = 4
找出的值: a[2] = 6 a[4] = 7
那如果我们想在一个单调递减的序列中找第一个小于等于或小于某个值的数呢?
只需要把修改后的cmp传入\(lower\_bound\)或\(upper\_bound\)函数内,将数组内元素的比较方式修改即可。
Usage:
bool cmp(const int &a,const int &b) { return a > b; }
int *p1=lower_bound(a+1,a+n+1,k,cmp);
int *p2=upper_bound(a+1,a+n+1,k,cmp);
其中\(a\)数组也可以为结构体数组,如果内嵌了重载函数可以不写cmp。
也就是说,只要让系统知道了这个数组元素的比较方式,在这种比较方式下数组在给定范围是\(有序\)的,即可使用这两个函数。
如果是\(a\)数组是整形变量,可以使用C++原生的比较函数(从大到小)。
\(lower\_bound(a+1,a+n+1,value,greater<int>())\)
STL函数 lower_bound 和 upper_bound 在算法竞赛中的用法的更多相关文章
- 二分检索函数lower_bound()和upper_bound()
二分检索函数lower_bound()和upper_bound() 一.说明 头文件:<algorithm> 二分检索函数lower_bound()和upper_bound() lower ...
- 算法竞赛中的常用JAVA API:PriorityQueue(优先队列)(转载)
算法竞赛中的常用JAVA API:PriorityQueue(优先队列) PriorityQueue 翻译过来就是优先队列,本质是一个堆, 默认情况下堆顶每次都保留最小值,每插入一个元素,仍动态维护堆 ...
- Aho-Corasick automaton(AC自动机)解析及其在算法竞赛中的典型应用举例
摘要: 本文主要讲述了AC自动机的基本思想和实现原理,如何构造AC自动机,着重讲解AC自动机在算法竞赛中的一些典型应用. 什么是AC自动机? 如何构造一个AC自动机? AC自动机在算法竞赛中的典型应用 ...
- 算法竞赛中的常用JAVA API :HashSet 和 TreeSet(转载)
算法竞赛中的常用JAVA API :HashSet 和 TreeSet set set容器的特点是不包含重复元素,也就是说自动去重. HashSet HashSet基于哈希表实现,无序. add(E ...
- 算法竞赛中的常用JAVA API :HashMap 和 TreeMap(转载)
算法竞赛中的常用JAVA API :HashMap 和 TreeMap 摘要 本文主要介绍Map接口下的HashMap和TreeMap. HashMap HashMap是基于哈希表的 Map 接口的实 ...
- 8.算法竞赛中的常用JAVA API :Calendar日期类
8.算法竞赛中的常用JAVA API :Calendar日期类 摘要 在蓝桥杯中有关于日期计算的问题,正好java中的Date类和Calendar类提供了对日期处理的一些方法.Date类大部分方法已经 ...
- 7.算法竞赛中的常用JAVA API :String 、StringBuilder、StringBuffer常用方法和区别(转载)
7.算法竞赛中的常用JAVA API :String .StringBuilder.StringBuffer常用方法和区别 摘要 本文将介绍String.StringBuilder类的常用方法. 在j ...
- 6.算法竞赛中的常用JAVA API :Math类(转载)
6.算法竞赛中的常用JAVA API :Math类 求最值 最小值 Math.min(int a, int b) Math.min(float a, float b) Math.min(double ...
- 算法竞赛中的常用JAVA API :大数类(转载)
5.算法竞赛中的常用JAVA API :大数类 摘要 java中的基础数据类型能存储的最大的二进制数是 2 ^ 63 - 1 对应的十进制数是9223372036854775807(long类型的最大 ...
随机推荐
- vs 中明明包含了头文件所在路径,但是却找不到头文件
vs基本不会出错,那么出错的只能是自己了. 哎,又被自己给蠢死了. 你可能在上面两个地方添加好了include 目录,但是却依然编译失败,失败的提示是找不到头文件所在路径,这是为什么呢. 很简单,因为 ...
- vue学习(二)模板页配置(bootstrap)
1.替换我们的显示页面 删除components下的所有文件,新建模板页文件夹 layout. //Layout.vue <template> <div> <header ...
- Centos7 LVM扩容实例
Centos7 lvm 扩容与以往版本有所不同 1.插入硬盘,我是在虚拟机上做的测试 直接添加一块5G的硬盘 2.系统读取硬盘信息 # echo "- - -" ...
- 线段树学习----C语言
/* 线段树学习:如果一个节点为i,那么他的左孩子为2I+1,右孩子为2i+2: */ #include<stdio.h> #define min(a,b) a<b?a:b; ]; ...
- JavaScript节流与防抖函数封装
js节流与防抖函数封装 常见应用场景: window的 resize 和 scroll 事件: 文字输入时的 keyup 事件: 元素拖拽.移动时的 mousemove 事件: 防抖 定义:多次触发事 ...
- 正则表达式过滤html注释内容
Regex.Replace("<!--(.|[\r\n])*?-->",string.Empty)
- java设计模式 - 单例模式(干货)
深度讲解23种设计模式,力争每种设计模式都刨析到底.废话不多说,开始第一种设计模式 - 单例. 作者已知的单例模式有8种写法,而每一种写法,都有自身的优缺点. 1,使用频率最高的写法,废话不多说,直接 ...
- fancybox图片灯箱功能
fancybox图片灯箱功能 在页面中引入几个文件 <script src="https://cdn.jsdelivr.net/npm/jquery@3.4.1/dist/jquery ...
- 什么是AOP面向切面编程思想
一.什么是AOP? 1.AOP不是一种语言,是一种编程范式 常见的编程范式: 面向过程.面向对象.函数式编程.事件驱动编程等 2.AOP可以解决特定问题,不能解决所有问题. 3.是面向对象的补充,不是 ...
- Spark应用开发调优要点总结
调试Spark应用性能的时候,首先应该理解spark是如何工作以及你的spark应用需要何种类型的资源.比如说,机器学习相关的spark应用更依赖cpu计算能力,ETL应用更依赖I/O能力,以此进行有 ...