二分查找模板及例题

文章目录

模板一:

cpp 复制代码
while(l < r){
	int mid = l + r >> 1;
	while(check(mid)) r = mid;
	else l = mid +1;
}

使用场景:

此模板用于找出满足条件的最小值,即尽量往左找。

解释:

当mid满足条件时,执行 r = m i d r=mid r=mid,将区间往左缩小,直到l==r时候找到答案 。

例题:

数的范围

题意:

给定一个按照升序排列的长度为 n n n的整数数组,以及 q q q个查询。对于每个查询,返回一个元素 k k k的起始位置和终止位置(位置从 0开始计数)。如果数组中不存在该元素,则返回 − 1 − 1 -1 -1 −1−1。

代码:

cpp 复制代码
#include<iostream>
#include<algorithm>
#include<cstring>

using namespace std;

const int N=100010;

int n,m;
int a[N];

int main()
{
	cin>>n>>m;
	
	for(int i=0;i<n;i++) cin>>a[i];
	
	while(m--)
	{
		int x;
		
		cin>>x;
		
		int l=0,r=n-1;
		while(l<r)
		{
			int mid=(l+r)>>1;
			if(a[mid]>=x) r=mid;
			else l=mid+1;
		}
		if(a[l]!=x)
		{
			cout<<"-1 -1"<<endl;
		}
		else
		{
			cout<<l<<" ";
			l=0,r=n-1;
			while(l<r)
			{
				int mid=(l+r+1)>>1;
				if(a[mid]<=x) l=mid;
				else r=mid-1;
			}
			cout<<l<<endl;
		}
	}
	return 0;
}

模板二:

cpp 复制代码
while(l < r){
	int mid = (l + r + 1) >> 1;//提醒:mid的更新方式不太一样
	while(check(mid)) l = mid;
	else r = mid - 1;
}

使用场景:

用于找出满足条件的最大值,即尽量往右找。

解释:

当 m i d mid mid满足条件时,执行操作 l = m i d l = mid l=mid,此时区间会向右边缩小。

例题:

Building an Aquarium

题意:

你喜欢养鱼,所以你决定建造一个水族馆。你有一块由 n n n 根柱子组成的珊瑚,其中 i i i 根柱子高 a i a _{i} ai 个单位。之后,你将在珊瑚周围建造一个水族箱,具体如下:

  • 选取一个整数 h h h --水箱的高度。在水箱两侧建造高度为 h h h的墙壁。
  • 然后,在水箱中注满水,使每一列的高度都是 h h h ,除非珊瑚的高度超过 h h h ,否则这一列不需要注水。

例如, a = [ 3 , 1 , 2 , 4 , 6 , 2 , 5 ] a=[3,1,2,4,6,2,5] a=[3,1,2,4,6,2,5] 和高度为 h = 4 h=4 h=4 ,最终总共需要使用 w = 8 w=8 w=8 个单位的水,如图所示。

你最多可以用 x x x 个单位的水来装满水箱,但你想尽可能建造最大的水箱。你能选择的 h h h 的最大值是多少?

代码:
cpp 复制代码
#include<iostream>
#include<algorithm>
#include<vector>
#include<cstring>
#define int long long

using namespace std;

void solve(){
	int n,x;
	
	cin>>n>>x;
	vector<int> a(n);
	
	for(int i=0;i<n;i++) cin>>a[i];
	
	int l=0;
	int r=2000000007;
	while(l<r){
		int ans=0;
		int mid=(r+l+1)/2;
		for(int i=0;i<n;i++) ans+=max((long long)0,mid-a[i]);
		if(ans<=x) l=mid;
		else r=mid-1;
	}
	
	cout<<l<<endl;
}
signed main(){
	int t;
	
	cin>>t;
	
	while(t--) solve();
	
	return 0;
}

由于本人写二分时,范围总是出错,总是把两个mid的更新方式搞混,特写此文章加深记忆。

相关推荐
PingdiGuo_guo18 分钟前
C++智能指针的知识!
开发语言·c++
Chuncheng's blog21 分钟前
CentOS 7如何编译安装升级gcc至7.5版本?
linux·运维·c++·centos
fail_to_code38 分钟前
递归法的递归函数何时需要返回值
算法
C137的本贾尼1 小时前
(每日一道算法题)二叉树剪枝
算法·机器学习·剪枝
吴声子夜歌1 小时前
OpenCV——Mat类及常用数据结构
数据结构·opencv·webpack
笑口常开xpr2 小时前
数 据 结 构 进 阶:哨 兵 位 的 头 结 点 如 何 简 化 链 表 操 作
数据结构·链表·哨兵位的头节点
BUG收容所所长2 小时前
栈的奇妙世界:从冰棒到算法的华丽转身
前端·javascript·算法
愚润求学2 小时前
【C++】类型转换
开发语言·c++
XRZaaa2 小时前
常见排序算法详解与C语言实现
c语言·算法·排序算法
@我漫长的孤独流浪3 小时前
数据结构测试模拟题(4)
数据结构·c++·算法