二分查找模板及例题

文章目录

模板一:

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

相关推荐
向阳@向远方20 分钟前
第二章 简单程序设计
开发语言·c++·算法
Mr_Xuhhh1 小时前
信号与槽的总结
java·开发语言·数据库·c++·qt·系统架构
github_czy1 小时前
RRF (Reciprocal Rank Fusion) 排序算法详解
算法·排序算法
liulilittle1 小时前
VGW 虚拟网关用户手册 (PPP PRIVATE NETWORK 基础设施)
开发语言·网络·c++·网关·智能路由器·路由器·通信
许愿与你永世安宁2 小时前
力扣343 整数拆分
数据结构·算法·leetcode
爱coding的橙子2 小时前
每日算法刷题Day42 7.5:leetcode前缀和3道题,用时2h
算法·leetcode·职场和发展
ruanjiananquan992 小时前
c,c++语言的栈内存、堆内存及任意读写内存
java·c语言·c++
满分观察网友z2 小时前
从一次手滑,我洞悉了用户输入的所有可能性(3330. 找到初始输入字符串 I)
算法
持梦远方2 小时前
C 语言基础入门:基本数据类型与运算符详解
c语言·开发语言·c++
YuTaoShao3 小时前
【LeetCode 热题 100】73. 矩阵置零——(解法二)空间复杂度 O(1)
java·算法·leetcode·矩阵