lower_bound和upper_bound的用法

本篇文章同步发表于 luogu-blog

两个函数用于 升序 降序 非递减序列(升序带并列),非递增序列(降序带并列)

这两个函数都是STL自带的二分查找函数,具有优秀的时间复杂度\(O(logn)\)

在头文件<algorithm>内,不过lower_bound不用<algorithm>好像不会报错。(逃~)

函数原型

_ForwardIterator lower_bound(_ForwardIterator _first,_ForwardIterator _last,const _Tp&__val)
_ForwardIterator upper_bound(_ForwardIterator _first,_ForwardIterator _last,const _Tp&__val)

升序(带并列)

lower_bound()upper_bound()默认在升序序列中进行二分查找,不需要添加参数。

lower_bound()在一个升序序列中,返回一个指向大于等于该元素的第一个迭代器。

如果没有大于等于该元素的元素,返回指向最后一位元素的后一位的迭代器,即last,注意last是越界的!

#include<cstdio>
#include<iostream>
#define LL long long
using namespace std;
int num[]={0,1,1,2,3,6,7,9,15,17,21,32,48}; //升序 
const int n=12;
int main()
{
	cout<<num[(lower_bound(num+1,num+n+1,8)-num)]<<endl; //result : 9
	//两种写法相同 
	cout<<*lower_bound(num+1,num+n+1,0)<<endl; //result : 1
	cout<<*lower_bound(num+1,num+n+1,1)<<endl; //result : 1
	cout<<*lower_bound(num+1,num+n+1,2)<<endl; //result : 2
	cout<<*lower_bound(num+1,num+n+1,3)<<endl; //result : 3
	cout<<*lower_bound(num+1,num+n+1,4)<<endl; //result : 6
	cout<<*lower_bound(num+1,num+n+1,5)<<endl; //result : 6
	cout<<*lower_bound(num+1,num+n+1,6)<<endl; //result : 6
	cout<<*lower_bound(num+1,num+n+1,7)<<endl; //result : 7
	cout<<*lower_bound(num+1,num+n+1,8)<<endl; //result : 9
	cout<<*lower_bound(num+1,num+n+1,9)<<endl; //result : 9
	cout<<*lower_bound(num+1,num+n+1,10)<<endl; //result : 15
	cout<<*lower_bound(num+1,num+n+1,15)<<endl; //result : 15
	cout<<*lower_bound(num+1,num+n+1,17)<<endl; //result : 17
	cout<<*lower_bound(num+1,num+n+1,22)<<endl; //result : 32
	cout<<*lower_bound(num+1,num+n+1,49)<<endl; //result : 0
	if(lower_bound(num+1,num+n+1,49)==num+n+1) 
		puts("lower_bound(num+1,num+n+1,49)==num+n+1"); 
			//result:lower_bound(num+1,num+n+1,49)==num+n+1
	//lower_bound()在一个升序序列中,返回一个指向大于等于该元素的第一个迭代器。 
	//如果没有大于等于该元素的元素,返回指向最后一位元素的后一位的迭代器; 
	return 0;
}

upper_bound()在一个升序序列中,返回一个指向大于该元素的第一个迭代器。

如果没有大于该元素的元素,返回指向最后一位元素的后一位的迭代器;

#include<cstdio>
#include<iostream>
#include<algorithm>
#define LL long long
using namespace std;
int num[]={0,1,1,2,3,6,7,9,15,17,21,32,48}; //升序 
const int n=12;
int main()
{
	cout<<num[upper_bound(num+1,num+n+1,8)-num]<<endl; //result :9
	//两种写法相同
	cout<<*upper_bound(num+1,num+n+1,0)<<endl;  //result :1
	cout<<*upper_bound(num+1,num+n+1,1)<<endl;  //result :2
	cout<<*upper_bound(num+1,num+n+1,2)<<endl;  //result :3
	cout<<*upper_bound(num+1,num+n+1,3)<<endl;  //result :6
	cout<<*upper_bound(num+1,num+n+1,4)<<endl;  //result :6
	cout<<*upper_bound(num+1,num+n+1,5)<<endl;  //result :6
	cout<<*upper_bound(num+1,num+n+1,6)<<endl;  //result :7
	cout<<*upper_bound(num+1,num+n+1,7)<<endl;  //result :9
	cout<<*upper_bound(num+1,num+n+1,8)<<endl;  //result :9
	cout<<*upper_bound(num+1,num+n+1,9)<<endl;  //result :15
	cout<<*upper_bound(num+1,num+n+1,16)<<endl;  //result :17
	cout<<*upper_bound(num+1,num+n+1,25)<<endl;  //result :32
	cout<<*upper_bound(num+1,num+n+1,32)<<endl;  //result :48
	cout<<*upper_bound(num+1,num+n+1,49)<<endl;  //result :0
	if(upper_bound(num+1,num+n+1,48)==num+n+1) 
		puts("upper_bound(num+1,num+n+1,48)==num+n+1");
			//result:upper_bound(num+1,num+n+1,48)==num+n+1
	//upper_bound()在一个升序序列中,返回一个指向大于该元素的第一个迭代器。 
	//如果没有大于该元素的元素,返回指向最后一位元素的后一位的迭代器; 
	return 0;
}

降序(带并列)

降序查找需要加一个参数。

比如在int类型的降序数列里查找。

bool cmp(const int &a,const int &b)
{
	return a>b;
}

类似sort

在升序内用小于号,降序内用大于号。

感性理解:就是前一个数和后一个数的关系啦。。

lower_bound(num,num+n,1,cmp)

当然也可以用STL自带的greater

lower_bound(num,num+n,1,greater<int>())

其他与升序一样。

upper_bound()lower_bound()一样。

#include<cstdio>
#include<iostream>
#include<algorithm>
#define LL long long
using namespace std;
int num[]={48,32,21,17,15,9,7,6,3,2,1,1}; //降序 
const int n=12;
bool cmp(const int &a,const int &b)
{
	return a>b;
}
int main()
{
	freopen(".out","w",stdout);
	cout<<*lower_bound(num,num+n,1,greater<int>())<<endl;
	cout<<*lower_bound(num,num+n,1,greater<int>())<<endl;
	cout<<*lower_bound(num,num+n,2,greater<int>())<<endl;
	cout<<*lower_bound(num,num+n,3,greater<int>())<<endl;
	cout<<*lower_bound(num,num+n,4,greater<int>())<<endl; 
	cout<<*lower_bound(num,num+n,5,greater<int>())<<endl;
	cout<<*lower_bound(num,num+n,6,greater<int>())<<endl; 
	cout<<*lower_bound(num,num+n,7,greater<int>())<<endl;
	cout<<*lower_bound(num,num+n,8,greater<int>())<<endl;
	cout<<*lower_bound(num,num+n,9,greater<int>())<<endl; 
	cout<<*lower_bound(num,num+n,10,greater<int>())<<endl;
	cout<<*lower_bound(num,num+n,15,greater<int>())<<endl; 
	cout<<*lower_bound(num,num+n,17,greater<int>())<<endl; 
	cout<<*lower_bound(num,num+n,22,greater<int>())<<endl; 
	cout<<*lower_bound(num,num+n,49,greater<int>())<<endl;  
	return 0;
}

\(result\)

1
1
2
3
3
3
6
7
7
9
9
15
17
21
48

结构体

竟然加入了可供\(DIY\)的参数,那就可以在一个结构体数组内实现二分查找了!

#include<cstdio>
#include<iostream>
#include<algorithm>
#define LL long long
using namespace std;
struct student
{
	int mark;
	int num;
};
student a[20];
bool cmp(const student &a,const student &b)
{
	return a.mark>b.mark;
}
int main()
{
	a[0]=student{100,0};
	a[1]=student{89,1};
	a[2]=student{89,2};
	a[3]=student{79,3};
	a[4]=student{69,4};
	a[5]=student{59,5};
	a[6]=student{49,6};
	a[7]=student{39,7};
	a[8]=student{29,8};
	a[9]=student{19,9};
	a[10]=student{9,10};
	student b={67,9};
	cout<<lower_bound(a,a+10,b,cmp)->mark<<endl;
	return 0;
}

\(result\)

59

特别鸣谢:热心网友之江学院石洗凡老师的帮助

posted @ 2020-08-12 15:40  cjlworld  阅读(1006)  评论(0编辑  收藏  举报