常用函数lower_bound() 和upper_bound()、优先队列(priority_queue)

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时,决定了右边的优先级高于左边的优先级。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值