C++二分查找

news2025/4/13 4:41:04

一、模板①:向下取整(mid = (l + r) >> 1

while (l < r) {
    int mid = l + r >> 1; // 等价于 (l + r) / 2(向下取整)
    if (check(mid)) r = mid; // 保留左半区
    else l = mid + 1;        // 舍弃左半区
}
适用场景
  1. 查找左边界(最小值)

    • 例如:在有序数组中找到 第一个大于等于目标值 的位置
    • 逻辑:当 check(mid) 满足条件时,说明目标值可能在左半区(包括 mid),因此右边界 r 缩小到 mid;否则,左边界 l 移动到 mid + 1
    • 关键特征:区间收缩时 保留左半区mid 向下取整可避免死循环
  2. 寻找满足条件的最小值

    • 例如:求满足 x² ≤ target 的最大整数 x(即平方根的整数部分)
    • 原因:向下取整确保中间值偏向左侧,逐步逼近最小可行解。

二、模板②:向上取整(mid = (l + r + 1) >> 1

while (l < r) {
    int mid = l + r + 1 >> 1; // 等价于 (l + r + 1) / 2(向上取整)
    if (check(mid)) l = mid;   // 保留右半区
    else r = mid - 1;         // 舍弃右半区
}
适用场景
  1. 查找右边界(最大值)

    • 例如:在有序数组中找到 最后一个小于等于目标值 的位置
    • 逻辑:当 check(mid) 满足条件时,说明目标值可能在右半区(包括 mid),因此左边界 l 移动到 mid;否则,右边界 r 缩小到 mid - 1
    • 关键特征:区间收缩时 保留右半区mid 向上取整可防止循环卡死
  2. 寻找满足条件的最大值

    • 例如:求巧克力切割的最大边长,使得总块数满足要求
    • 原因:向上取整确保中间值偏向右侧,逐步逼近最大可行解。

三、核心区别与选择依据

特征模板①(向下取整)模板②(向上取整)
mid 计算mid = (l + r) / 2mid = (l + r + 1) / 2
区间收缩保留左半区(r = mid保留右半区(l = mid
适用方向左边界、最小值、左侧优先右边界、最大值、右侧优先
防死循环确保 l 和 r 逐步靠近避免 l 和 r 无法缩小范围
选择原则
  1. 分析问题目标:明确是找左边界还是右边界,是求最小值还是最大值。
  2. 观察区间更新:若更新 l = mid,则必须向上取整;若更新 r = mid,则需向下取整
  3. 验证边界条件:通过极端用例(如 l 和 r 相邻时)检查是否可能陷入死循环。

例题:

问题描述

小蓝有一个神奇的炉子用于将普通金属 O 冶炼成为一种特殊金属 X。这个炉子有一个称作转换率的属性 V,V 是一个正整数,这意味着消耗 V 个普通金属 O 恰好可以冶炼出一个特殊金属 XX,当普通金属 O 的数目不足 V 时,无法继续冶炼。

现在给出了 N 条冶炼记录,每条记录中包含两个整数 A 和 B,这表示本次投入了 A 个普通金属 O,最终冶炼出了 B 个特殊金属 X。每条记录都是独立的,这意味着上一次没消耗完的普通金属 O 不会累加到下一次的冶炼当中。

根据这 N 条冶炼记录,请你推测出转换率 V 的最小值和最大值分别可能是多少,题目保证评测数据不存在无解的情况。

输入格式

第一行一个整数 N,表示冶炼记录的数目。

接下来输入 N 行,每行两个整数 A、B,含义如题目所述。

输出格式

输出两个整数,分别表示 V 可能的最小值和最大值,中间用空格分开。

#include<bits/stdc++.h>  // 包含所有标准库头文件(实际工程中不建议使用)

#define rep(i, a, b) for(int i = a; i < b; i++)  // 简化循环的宏定义

using namespace std;
const int N = 1e4 + 10;  // 定义常量(但代码中未实际使用)
int n;

// 二分查找函数:寻找满足条件的最大/最小值[6,8](@ref)
int get(int a, int b) 
{
    int l = 1, r = a;  // 初始化搜索范围为[1, a]
    while(l < r)  // 标准二分查找结构[7](@ref)
    {
        int mid = l + r >> 1;  // 等效于(l + r)/2(向下取整)
        // 核心判断条件:当a/mid <= b时,收缩右边界
        if(a / mid <= b)
            r = mid;    // 满足条件时尝试更小的值
        else 
            l = mid + 1; // 不满足条件时增大下界
    }
    return r;  // 最终收敛到满足条件的最小值[8](@ref)
}

int main()
{
    cin >> n;  // 读取输入的对数
    
    // 初始化极值(minv为下限,maxv为上限)
    int minv = 1;         // 最小值的初始下界
    int maxv = 1e9;       // 最大值的初始上界
    
    int a, b;
    rep(i, 0, n)  // 遍历每个输入对
    {
        scanf("%d%d", &a, &b);
        // 关键逻辑:对多个区间取交集[10,11](@ref)
        // 更新最小值下限(取所有区间的最大左端点)
        minv = max(minv, get(a, b));
        // 更新最大值上限(取所有区间的最小右端点)
        maxv = min(maxv, get(a, b - 1) - 1);
    }
    
    // 输出最终的交集区间
    cout << minv << " " << maxv;
    
    return 0;
}

问题描述

儿童节那天有 K 位小朋友到小明家做客。小明拿出了珍藏的巧克力招待小朋友们。

小明一共有 N 块巧克力,其中第 i 块是 Hi×Wi 的方格组成的长方形。为了公平起见,

小明需要从这 N块巧克力中切出 K 块巧克力分给小朋友们。切出的巧克力需要满足:

  1. 形状是正方形,边长是整数;

  2. 大小相同;

例如一块 6×5 的巧克力可以切出 6 块 2×2 的巧克力或者 2 块 3×3 的巧克力。

当然小朋友们都希望得到的巧克力尽可能大,你能帮小明计算出最大的边长是多少么?

输入描述

第一行包含两个整数 N,K (1≤N,K≤105)。

以下 N 行每行包含两个整数 Hi,Wi (1≤Hi,Wi≤105)。

输入保证每位小朋友至少能获得一块 1x1 的巧克力。

输出描述

输出切出的正方形巧克力最大可能的边长。

#include<bits/stdc++.h>  
using namespace std; 
  
const int N=1e5+5; // 定义常数N,表示矩形数量的上限  
int h[N],w[N]; // 定义两个数组,分别存储每个矩形的高和宽  
int n,k,m; // 定义变量n表示矩形数量,k表示目标正方形数量,m用于存储矩形尺寸的最大值  
  
// 定义一个检查函数,判断给定的正方形边长mid是否满足条件  
bool check(int mid){  
	int sum=0; // 用于计算可以切割出的正方形数量  
	for(int i=0;i<n;i++){ // 遍历每个矩形  
		sum+=(h[i]/mid)*(w[i]/mid); // 计算当前矩形可以切割出的正方形数量,并累加到sum中  
	}  
	if(sum>=k){ // 如果满足至少k个正方形的要求  
		return true;  // 返回true  
	}else{  
		return false; // 否则返回false  
	}  
}  
  
 
void solve(){  
	int l=1,r=m; // 定义二分查找的左右边界,l为最小可能边长1,r为矩形的最大尺寸  
	while(l<r){ // 当左边界小于右边界时,继续二分查找  
		int mid=l+(r-l)/2; // 计算中点,并向上取整(因为l+r可能是奇数)  
		if(check(mid)){ // 如果mid满足条件  
			l=mid; // 更新左边界为mid,继续寻找更小的满足条件的边长  
		}else{  
			r=mid-1; // 否则,更新右边界为mid-1,寻找更大的边长  
		}  
	}  
	cout<<l<<'\n'; // 输出最小的满足条件的边长  
}   
  
signed main(){  
	ios::sync_with_stdio(0); // 取消C++和C的输入输出同步,加快输入输出速度  
	cin.tie(0); // 解除cin与cout的绑定,加快输入输出速度  
	cout.tie(0);	  
	cin>>n>>k; // 输入矩形数量n和目标正方形数量k  
	for(int i=0;i<n;i++){ // 遍历每个矩形  
		cin>>h[i]>>w[i]; // 输入矩形的高和宽  
		m=max(h[i],m); // 更新m为矩形尺寸的最大值  
		m=max(w[i],m);  
	}  
	solve(); 
	return 0;  
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2333548.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

通过AWS EKS 生成并部署容器化应用

今天给大家分享一个实战例子&#xff0c;如何在EKS上创建容器化应用并通过ALB来发布。先介绍一下几个基本概念&#xff1a; IAM, OpenID Connect (OIDC) 2014 年&#xff0c;AWS Identity and Access Management 增加了使用 OpenID Connect (OIDC) 的联合身份支持。此功能允许…

nginx入门,部署静态资源,反向代理,负载均衡使用

Nginx在linux上部署静态资源 概念介绍 Nginx可以作为静态web服务器来部署静态资源。这里所说的静态资源是指在服务端真实存在&#xff0c;并且能够直接展示的一些文件&#xff0c;比如常见的html页面、css文件、js文件、图片、视频等资源。 相对于Tomcat&#xff0c;Nginx处理…

智膳优选 | AI赋能的智慧食堂管理专家 —— 基于飞书多维表格和扣子(Coze)的智能解决方案

智膳优选 | AI赋能的智慧食堂管理专家 基于飞书多维表格和扣子&#xff08;Coze&#xff09;的智能解决方案 数据驱动餐饮管理&#xff0c;让每一餐都是营养与经济的完美平衡&#xff01; “智膳优选”通过整合飞书与Coze&#xff0c;将数据智能引入校园餐饮管理&#xff0…

最新的es版本忘记密码,重置密码

刚刚安装了最新的es版本,就忘了密码,怎么重置密码呢? 一、进入es的斌目录 #进入es文件/bin 目录 ./elasticsearch-reset-password -u elastic 二 、输入对应的密码 然后再次访问 我的是去掉了ssl的访问 三、如果报错:解决 [main] WARN

Compose Multiplatform+Kotlin Multiplatfrom 第五弹跨平台 截图

截图功能 Compose MultiplatformKotlin Multiplatfrom下实现桌面端的截图功能&#xff0c;起码搞了两星期&#xff0c;最后终于做出来了&#xff0c;操作都很流畅&#xff0c;截取的文件大小也正常&#xff0c;可参考支持讨论&#xff01; 功能效果 代码实现 //在jvmMain下创…

Elasticearch数据流向

Elasticearch数据流向 数据流向图 --- config: layout: elk look: classic theme: mc --- flowchart LR subgraph s1["图例"] direction TB W["写入流程"] R["读取流程"] end A["Logstash Pipeline"] -- 写入请求 --> B["Elas…

在docker里装rocketmq-console

首先要到github下载&#xff08;这个一般是需要你有梯子&#xff09; GitHub - apache/rocketmq-externals at release-rocketmq-console-1.0.0 如果没有梯子&#xff0c;用下面这个百度网盘链接下 http://链接: https://pan.baidu.com/s/1x8WQVmaOBjTjss-3g01UPQ 提取码: fu…

使用Python写入JSON、XML和YAML数据到Excel文件

在当今数据驱动的技术生态中&#xff0c;JSON、XML和YAML作为主流结构化数据格式&#xff0c;因其层次化表达能力和跨平台兼容性&#xff0c;已成为系统间数据交换的通用载体。然而&#xff0c;当需要将这类半结构化数据转化为具备直观可视化、动态计算和协作共享特性的载体时&…

x-cmd install | Slumber - 告别繁琐,拥抱高效的终端 HTTP 客户端

目录 核心优势&#xff0c;一览无遗安装应用场景&#xff0c;无限可能示例告别 GUI&#xff0c;拥抱终端 还在为调试 API 接口&#xff0c;发送 HTTP 请求而苦恼吗&#xff1f;还在各种 GUI 工具之间切换&#xff0c;只为了发送一个简单的请求吗&#xff1f;现在&#xff0c;有…

apijson 快速上手

apijson是强大的工具&#xff0c;简化了CRUD的操作&#xff0c;只要有数据库表&#xff0c;就能自动生成RESTFUL接口。但初次上手也是摸索了很长时间&#xff0c;尤其是部署与使用上&#xff0c;这里尝试以初学者角度来说下&#xff1a; 一、好处 1、对于简单的应用&#xff…

3D激光轮廓仪知识整理

文章目录 1.原理和应用场景1.1 相机原理1.1.1 测量原理1.1.2 相机激光器1.1.3 沙姆镜头1.1.4 相机标定1.1.5 中心线提取 1.2 应用场景1.2.1 测量相关应用1.2.2 缺陷检测相关应用 2.相机参数介绍及选型介绍2.1 成像原理2.2 原始图成像2.3 生成轮廓图2.4 相机规格参数2.4.1 单轮廓…

Stable Diffusion+Pyqt5: 实现图像生成与管理界面(带保存 + 历史记录 + 删除功能)——我的实验记录(结尾附系统效果图)

目录 &#x1f9e0; 前言 &#x1f9fe; 我的需求 &#x1f527; 实现过程&#xff08;按功能一步步来&#xff09; &#x1f6b6;‍♂️ Step 1&#xff1a;基本图像生成界面 &#x1f5c3;️ Step 2&#xff1a;保存图片并显示历史记录 &#x1f4cf; Step 3&#xff1a…

使用WasmEdge将InternLM集成到Obsidian,打造本地智能笔记助手

本文来自社区投稿&#xff0c;作者Miley Fu&#xff0c;WasmEdge Runtime 创始成员。 本文将介绍如何通过 WasmEdge 将书生浦语&#xff08;InternLM&#xff09;大模型部署在本地&#xff0c;并与 Obsidian 笔记软件集成&#xff0c;从而在笔记软件中直接利用大模型实现文本总…

java导入excel更新设备经纬度度数或者度分秒

文章目录 一、背景介绍二、页面效果三、代码0.pom.xml1.ImportDevice.vue2.ImportDeviceError.vue3.system.js4.DeviceManageControl5.DeviceManageUserControl6.Repeater7.FileUtils8.ResponseModel9.EnumLongitudeLatitude10.词条 四、注意点本人其他相关文章链接 一、背景介…

视频设备轨迹回放平台EasyCVR远程监控体系落地筑牢国土监管防线

一、背景概述 我国土地资源遭违法滥用的现象愈发严峻&#xff0c;各类土地不合理利用问题频发。不当的土地开发不仅加剧了地质危害风险&#xff0c;导致良田受损、森林资源的滥伐&#xff0c;还引发了煤矿无序开采、城市开发区违建等乱象&#xff0c;给国家宝贵的土地资源造成…

Stable Diffusion 四重调参优化——项目学习记录

学习记录还原&#xff1a;在本次实验中&#xff0c;我基于 Stable Diffusion v1.5模型&#xff0c;通过一系列优化方法提升生成图像的质量&#xff0c;最终实现了图像质量的显著提升。实验从基础的 Img2Img 技术入手&#xff0c;逐步推进到参数微调、DreamShaper 模型和 Contro…

我可能用到的网站和软件

我可能用到的网站和软件 程序员交流的网站代码管理工具前端组件库前端框架在线工具人工智能问答工具学习的网站Windows系统电脑的常用工具 程序员交流的网站 csdn博客博客园 - 开发者的网上家园InfoQ - 软件开发及相关领域-极客邦掘金 (juejin.cn) 代码管理工具 GitHub 有时…

FPGA状态机设计:流水灯实现、Modelsim仿真、HDLBits练习

一、状态机思想 1.概念 状态机&#xff08;Finite State Machine, FSM&#xff09;是计算机科学和工程领域中的一种抽象模型&#xff0c;用于描述系统在不同状态之间的转换逻辑。其核心思想是将复杂的行为拆解为有限的状态&#xff0c;并通过事件触发状态间的转移。 2.状态机…

2024年第十五届蓝桥杯CC++大学A组--成绩统计

2024年第十五届蓝桥杯C&C大学A组--成绩统计 题目&#xff1a; 动态规划&#xff0c; 对于该题&#xff0c;考虑动态规划解法&#xff0c;先取前k个人的成绩计算其方差&#xff0c;并将成绩记录在数组中&#xff0c;记录当前均值&#xff0c;设小蓝已检查前i-1个人的成绩&…

Kotlin 学习-集合

/*** kotlin 集合* List:是一个有序列表&#xff0c;可通过索引&#xff08;下标&#xff09;访问元素。元素可以在list中出现多次、元素可重复* Set:是元素唯一的集合。一般来说 set中的元素顺序并不重要、无序集合* Map:&#xff08;字典&#xff09;是一组键值对。键是唯一的…