1、lower_bound() 和upper_bound()
-
lower_bound() 和upper_bound() 都是基于二分查找在一个排好序的数组或容器(如 vector, list, set )中进行快速查找的函数,位于 标准库中,由于采用二分查找,所以函数的时间复杂度是 O(log_2^n)
-
划重点!基于二分查找!数组或容器必须有序!
函数使用:
-
lower_bound(begin, end, num):适用于从小到大排序的有序序列,从数组/容器的begin 位置起,到 end−1 位置结束,查找第一个大于等于 num 的数字。
- 若找到则返回该数字的地址,通过减去起始地址 begin 的技巧可以求得其在数组/容器中的下标,如 lower_bound(arr, arr+n, 3)-arr 表示在数组 arr 中查找第一个大于等于 3 的元素在数组中的下标
- 若找不到,则返回 end,即数组/容器最后一个元素的下一个元素
-
upper_bound(begin, end, num):适用于从小到大排序的有序序列,从数组/容器的 begin 位置起,到 end−1 位置结束,查找第一个大于 num 的数字。
- 若找到则返回该数字的地址,通过减去起始地址 b e g i n beginbegin 的技巧可以求得其在数组/容器中的下标,如 upper_bound(arr, arr+n, 3)−arr 表示在数组 arr 中查找第一个大于 3 的元素在数组中的下标。
- 若找不到,则返回 end,即数组/容器最后一个元素的下一个元素。
-
lower_bound(begin, end, num, greater()):适用于从大到小排序的有序序列,从数组/容器的 begin 位置起,到 end−1 位置结束,查找第一个小于等于 num 的数字。
- 若找到则返回该数字的地址,通过减去起始地址 begin 的技巧可以求得其在数组/容器中的下标,如 lower_bound(arr, arr+n,3, greater())−arr 表示在数组 arr 中查找第一个小于等于 3的元素在数组中的下标。
- 若找不到,则返回 end,即数组/容器最后一个元素的下一个元素。
-
upper_bound(begin, end, num,greater()):适用于从大到小排序的有序序列,从数组/容器的 begin 位置起,到 end−1 位置结束,查找第一个小于 num 的数字。
-
若找到则返回该数字的地址,通过减去起始地址 begin 的技巧可以求得其在数组/容器中的下标,如 upper_bound(arr, arr+n,3, greater())−arr 表示在数组 arr 中查找第一个小于 3 的元素在数组中的下标。
-
若找不到,则返回 end,即数组/容器最后一个元素的下一个元素。
-
案例代码:
#include<bits/stdc++.h>
#define x first
#define y second
using namespace std;
typedef long long ll;
typedef pair<int,int> PII;
// 解题思路:
const int N=1e5+5;
int main() {
// 升序
int arr[]={1,3,2,8,5};
sort(arr,arr+5);
cout<<"序列为(从小到大排序):";
for(auto x:arr) cout<<x<<' ';
cout<<endl;
// 1.lower_bound
cout<<lower_bound(arr,arr+5,5)-arr<<endl; // 第一个大于等于5的是5,下标是3
// 2.upper_bound
cout<<upper_bound(arr,arr+5,6)-arr<<endl; // 第一个大于6的是8,下标是4
// 降序
sort(arr,arr+5,greater<int>()); // greater<int>()表示降序规则
cout<<"序列为(从大到小排序):";
for(auto x:arr) cout<<x<<' ';
cout<<endl;
// 3.lower_bound
cout<<lower_bound(arr,arr+5,3,greater<int>())-arr<<endl; // 第一个小于等于3的是3,下标是2
// 4.upper_bound
cout<<upper_bound(arr,arr+5,3,greater<int>())-arr<<endl; // 第一个小于等于3的是2,下标是3
return 0;
}
2、优先队列(priority_queue)
是队列的变体,需要包含头文件==#include==,和queue不同的在于可以自定义其中数据的优先级,让优先级高的排在队列前面,优先出队。
优先队列具有队列的所有特性,包括基本操作,只是在这基础上添加了内部的一个排序,它本质是一个堆实现的。
和队列基本操作相同:
- top 访问队头元素
- empty 队列是否为空
- size 返回队列内元素个数
- push 插入元素到队尾 (并排序)
- emplace 原地构造一个元素并插入队列
- pop 弹出队头元素
- swap 交换内容
定义:priority_queue<Type, Container, Functional>
Type:数据类型,Container:容器类型,Functional:比较方式,(只传基本数据类型时,默认是大顶堆)
- 排序:
less变成升序(从左到右遍历下标时,数组元素是从小到大)
greater变成降序(从左到右遍历下标时,数组元素是从大到小- 建堆:
less变成大顶堆(从上层到下层,堆元素是从大到小,同层之间随便)
greater变成小顶堆(从上层到下层,堆元素是从小到大,同层之间随便)
//降序队列 小顶堆
priority_queue <int,vector<int>,greater<int> > q;
//升序队列 大顶堆
priority_queue <int,cevtor<int>,less<int> > q;
less:
template struct less {
bool operator() (const T& x, const T& y) const {return x<y;}
typedef T first_argument_type;
typedef T second_argument_type;
typedef bool result_type;
};
优先队列里面按照优先级决定出队的顺序,在<的定义里,返回true时,决定了右边的优先级高于左边的优先级。