二分查找模板及例题

文章目录

模板一:

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的更新方式搞混,特写此文章加深记忆。

相关推荐
wljy11 小时前
二、进制状态转换
linux·运维·服务器·c语言·c++
云泽8081 小时前
笔试算法 -位运算篇(二):从唯一字符到消失数字
c++·算法·位运算
ʚ希希ɞ ྀ1 小时前
不同路径|| -- dp
算法
繁华落尽,倾城殇?1 小时前
[C++11] : atomic,nullptr,default/delete,enum class
开发语言·c++·c++11·nullptr·atomic·enum class·default/delete
代码村新手2 小时前
C++-二叉搜索树
开发语言·c++
IT 行者2 小时前
SimHash 与 MinHash:相似性计算的双子星算法
算法·hash·比对
智者知已应修善业3 小时前
【51单片机8位数码管动态显示日期小数点风格】2023-11-13
c++·经验分享·笔记·算法·51单片机
智者知已应修善业3 小时前
【51单片机有三个LED 分别第一个灯闪三下 再到第二个灯又闪三下 再到第三个灯又闪三下 就这样循环程序】2023-11-16
c++·经验分享·笔记·算法·51单片机
小娄~~4 小时前
C语言卷子错题集
c语言·开发语言·数据结构