蓝桥杯高频考点——二分(含C++源码)

二分

  • 基本框架
  • 整数查找(序列二分的模版题 建议先做)
    • 满分代码及思路
      • solution
  • 子串简写
    • 满分代码及思路
      • solution 1(暴力 模拟双指针70分)
      • solution 2(二分 AC)
  • 管道
    • 满分代码及思路
    • 样例解释与思路分析
      • solution
  • 最大通过数
    • 满分代码及思路
      • solution 1(贪心 50分)
      • 问题
      • solution 2(二分 AC)

基本框架

二分查找的思维确实非常简单 就是引入一个猜炸弹编号的问题 相信大家玩过对吧 假如炸弹是0-100中间的一个数字 不会玩的人可能一个一个猜 会玩的人一般上来就猜50 25 …

二分查找代码中的细节很重要但是真正的坑根本就不是那个细节问题,而是在于到底要给 mid 加一还是减一,while 里到底用 <= 还是 <,

这就要分别对应两种写法 :
一种是左闭右闭区间 一种是左闭右开区间 讲解视频我附在这里:

代码随想录的详细讲解

labuladong 算法笔记 :

在这里插入图片描述

整数查找(序列二分的模版题 建议先做)

在这里插入图片描述
题目链接

满分代码及思路

首先题目其实说的非常直白就是根据给的flag(1 2 3 4 )分别对应四种不同的查询方案 那么我们的main函数就分别对于这四种情况 分别调用函数返回结果即可

做完你再看 序列二分的本质上 是不是 在有限的一个区间或者序列中 快速找到满足条件的数

solution

#include <iostream>
using namespace std;
int n, q;
const int N = 1e5 + 9;
int a[N]; // 存一下序列A
int flag; // 取决于我们该怎么去查找
int l, r, x;
int ans;// 输出 A[l∼r] 中等于 x 最左边的数的下标,若不存在输出 -1
void search1(int l, int r, int x) {ans = -1;while (l <= r) {int mid = l + (r - l) / 2;if (a[mid] == x) {ans = mid;r = mid - 1;} else if (a[mid] < x) {l = mid + 1;} else {r = mid - 1;}}
}// 输出 A[l∼r] 中等于 x 最右边的数的下标,若不存在输出 -1
void search2(int l, int r, int x) {ans = -1;while (l <= r) {int mid = l + (r - l) / 2;if (a[mid] == x) {ans = mid;l = mid + 1;} else if (a[mid] < x) {l = mid + 1;} else {r = mid - 1;}}
}// 输出 A[l∼r] 中大于等于 x 的第一个数的下标,若不存在输出 -1
void search3(int l, int r, int x) {ans = -1;while (l <= r) {int mid = l + (r - l) / 2;if (a[mid] >= x) {ans = mid;r = mid - 1;} else {l = mid + 1;}}
}// 输出 A[l∼r] 中大于 x 的第一个数的下标,若不存在输出 -1
void search4(int l, int r, int x) {ans = -1;while (l <= r) {int mid = l + (r - l) / 2;if (a[mid] > x) {ans = mid;r = mid - 1;} else {l = mid + 1;}}
}int main() {cin >> n >> q;for (int i = 1; i <= n; i++) {cin >> a[i];}while (q--) {cin >> flag >> l >> r >> x;if (flag == 1) {search1(l , r , x);} else if (flag == 2) {search2(l , r , x);} else if (flag == 3) {search3(l , r , x);} else if (flag == 4) {search4(l , r , x);}cout << ans << endl;}return 0;
}    

子串简写

在这里插入图片描述
题目链接

满分代码及思路

solution 1(暴力 模拟双指针70分)

对于这道题目其实我首先想到的就是双指针,具体拿这题来说就是,我们现在有两个指针left right 现在要做的就是 在给定的字符串中枚举出所有同时满足

1.长度大于等于K;
2.以c1开头以c2结尾

以上两个条件的所有子串 对吧
那么就很好办了呀 我们先让left指针找到c1,然后通过不断移动right
枚举出所有以left此时位置为左端点 且满足条件的所有合法情况
每次更新答案count 就好 最后输出一下
但是有几个比较大的样例超时了 这时候我们就需要想办法优化一下:
在这里插入图片描述
因为我们这个双指针的方法 主要依靠两个for循环 时间复杂度是O(n*n)

Q:所以我们要思考的是我们可以去优化的点在哪啊?

也就是说这个代码有什么重复且不必要的操作吗?

我觉得这个思考很重要很重要

A:二分相对于双指针优化的点是不是在于c2位置的确定啊 因为双指针需要枚举right每一种情况吧 因为我们就像一个瞎子 我们的right只有走到它的儿子面前才能跟他相认

具体来说,在双指针方法里,对于每一个以 c1 开头的位置,代码需要从 left + K - 1 开始,逐个枚举所有可能的 right 位置,直到找到以 c2 结尾的位置,从而判断是否满足子串长度大于等于 K 的条件

二分查找方法首先记录下所有 c1 和 c2 出现的位置。对于每一个 c1 出现的位置,要寻找满足子串长度大于等于 K 的 c2 位置时,它利用 c2 位置数组的有序性(因为位置是按顺序记录的)进行二分查找
此时我们的right指针他是一个视力很好的人 他知道自己的子女 在这条路的哪个方位

二分查找每次将搜索范围缩小一半,其时间复杂度为 (O(log m)),其中 m 是 c2 出现的次数。对于所有 c1 出现的位置都进行二分查找,整体时间复杂度就是 (O(n log m)),在一般情况下可以近似看作 (O(n log n)),相比于双指针方法的 (O(n^2)) 有了显著的优化。

#include <iostream>
#include <string>// 引入标准库命名空间
using namespace std;// 双指针方法
int double_point(int K, const string& S, char c1, char c2) {int n = S.length();int count = 0;for (int left = 0; left < n; ++left) {if (S[left] == c1) {for (int right = left + K - 1; right < n; ++right) {if (S[right] == c2) {++count;}}}}return count;
}int main() {int K;string S;char c1, char c2;// 读取输入cin >> K;cin >> S >> c1 >> c2;// 计算结果int result = double_point(K, S, c1, c2);// 输出结果cout << "双指针方法结果: " << result << endl;return 0;
}

solution 2(二分 AC)

#include <iostream>
#include <string>
#include <vector>
#include <algorithm>using namespace std;// 二分查找方法
int binary_search(int K, const string& S, char c1, char c2) {int n = S.length();vector<int> start;vector<int> end;// 记录 c1 和 c2 出现的位置for (int i = 0; i < n; ++i) {if (S[i] == c1) {start.push_back(i);}if (S[i] == c2) {end.push_back(i);}}int count = 0;for (int s : start) {// 二分查找满足条件的 c2 位置int left = 0, right = end.size() - 1;int target = s + K - 1;while (left <= right) {int mid = left + (right - left) / 2;if (end[mid] >= target) {right = mid - 1;} else {left = mid + 1;}}count += end.size() - left;}return count;
}int main() {int K;string S;char c1, c2;// 读取输入cin >> K;cin >> S >> c1 >> c2;// 计算结果int result = binary_search(K, S, c1, c2);// 输出结果cout << "二分查找方法结果: " << result << endl;return 0;
}    

管道

在这里插入图片描述
题目链接

满分代码及思路

代码和思路参考:视频讲解
BZW :这是我偶然刷到的一个up 真的很优秀很有思维

样例解释与思路分析

对于这道题目首先我们需要搞清楚 我们要干嘛
可以将这个管道看成一条线段 阀门就是线段上的点
我们需要明确的是这个阀门只要一打开就会向左右两边同时灌水 就可以看成是以这个点为中心向左右两边延伸 length的长度
并且 len与时间t的函数是一个单调递增函数

在这里插入图片描述

solution

#include <iostream>
#include <bits/stdc++.h>
using namespace std;
int n,len;
const int N=1e5+10;
int a[N][2];//存储输入每个阀门的位置和时间
struct door{int L;//位置int S;//时刻
}d[N];
struct line{int l;int r;
}w[N];
//sort比较函数 从小到大排左端点 如果一样就把右端点大的放后面
bool cmp(line A,line B)
{if(A.l!=B.l){return A.l<B.l;}else{return A.r<B.r;}}
bool check(int x)
{int cnt=0;for(int i=0;i<n;i++)//生成区间{if(x<d[i].S)continue;w[cnt].l=d[i].L-(x-d[i].S);w[cnt].r=d[i].L+(x-d[i].S);cnt++;}sort(w,w+cnt,cmp);int last=0;//线段合并for(int i=0;i<cnt;i++){//为什么是last+1 因为题目把这些管道看作是一个个离散的点 所以只要我们新区间的右端点>last+1(l=临界情况)//就return falseif(w[i].l>last+1){return false;}last=max(w[i].r,last);}if(last<len){return false;}return true;
}
int main()
{cin>>n>>len;for(int i=0;i<n;i++){cin>>d[i].L>>d[i].S;}//读入完成int mid=0;int l=0;int r=2e9;//最坏的情况就是从1ee9开始流 直到2e9才能铺满管道//二分答案 左闭右开写法while(l<r){mid=(l+r)/2;if(check(mid))//如果mid这个时间能铺满整个管道 说明在mid右边的时刻都是合法的//那么我们就需要操作://不减1是因为我们不能保证mid是不是临界点 也就是我们不知道mid-1是什么情况{r=mid;}else{l=mid+1;}}cout<<l<<endl;return 0;
}

最大通过数

在这里插入图片描述
题目链接

满分代码及思路

solution 1(贪心 50分)

// 我们现在需要做的就是用这K个水晶 通过尽可能多的关卡 并且我们不需要关心水晶的分配问题
// 也就是说两个人共享一个背包 首先在闯关之前 我肯定想要比较一下左右两个入口 
// 优先通过消耗水晶小的关卡 这样才能保证 最好通过关卡的数量最多
#include <iostream>
using namespace std;
const int N = 2e5 + 9;
int a[N], b[N]; // 分别表示左右两边关卡的能源数量
int n, m, k;    // 初始状态下有n+m道关卡 一共有K个水晶
int passCount;void work() {int i = 0, j = 0;// 先处理左右两边都有的关卡while (i < n && j < m) {if (a[i] <= b[j] && k >= a[i]) {passCount++;k -= a[i];i++;} else if (k >= b[j]) {passCount++;k -= b[j];j++;} else {break;}}// 处理左边剩余的关卡while (i < n && k >= a[i]) {passCount++;k -= a[i];i++;}// 处理右边剩余的关卡while (j < m && k >= b[j]) {passCount++;k -= b[j];j++;}
}int main() {cin >> n >> m >> k;for (int i = 0; i < n; i++) {cin >> a[i];}for (int j = 0; j < m; j++) {cin >> b[j];}work();cout << passCount;return 0;
}

问题

在这里插入图片描述

solution 2(二分 AC)

#include <bits/stdc++.h>
using namespace std;
using ll = long long;const int N = 2e5 + 4;
ll a[N], b[N], pre_a[N], pre_b[N];
ll n, m, k;// 检查是否可以通过 mid 个关卡
bool check(ll mid) {bool ok = false;  // 记录 mid 关卡数是否有可行的方案,不关心 a,b 各通过几关// 从关卡数少的人开始枚举(mid > max(m,n) 时)for (ll i = 0; i <= min(min(m, n), mid); ++i) {// 保证另外一个人有足够的关卡数来凑为 mid 关,没有就跳过if (mid - i > max(m, n)) continue;// 从关卡数少的人开始枚举(保证不越界)if (m <= n && pre_b[i] + pre_a[mid - i] <= k) {ok = true;} else if (n < m && pre_a[i] + pre_b[mid - i] <= k) {ok = true;}}return ok;
}// 解决问题的函数
void solve() {cin >> n >> m >> k;// 读取左边入口每个关卡所需的宝石数for (int i = 1; i <= n; ++i) {cin >> a[i];}// 读取右边入口每个关卡所需的宝石数for (int i = 1; i <= m; ++i) {cin >> b[i];}// 计算 a[i] 前缀和,代表 a 通过 i 关所需的宝石for (int i = 1; i <= n; ++i) {pre_a[i] = pre_a[i - 1] + a[i];}// 计算 b[i] 前缀和,代表 b 通过 i 关所需的宝石for (int i = 1; i <= m; ++i) {pre_b[i] = pre_b[i - 1] + b[i];}// 二分查找最大通过的关卡数ll l = 0, r = m + n + 10;while (l + 1 != r) {ll mid = (l + r) >> 1;if (check(mid)) {l = mid;  // mid 可行,说明 mid 可能可以更大,更新 l} else {r = mid;}}cout << l;  // l 为答案
}int main() {ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);int t = 1;// cin >> t;while (t--) {solve();}return 0;
}

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Rust vs. Go: 性能测试(2025)

本内容是对知名性能评测博主 Anton Putra Rust vs. Go (Golang): Performance 2025 内容的翻译与整理, 有适当删减, 相关数据和结论以原作结论为准。 再次对比 Rust 和 Go&#xff0c;但这次我们使用的是最具性能优势的 HTTP 服务器库---Hyper&#xff0c;它基于 Tokio 异步运…

【NUUO 摄像头】(弱口令登录漏洞)

漏洞简介&#xff1a;NUUO 是NUUO公司的一款小型网络硬盘录像机设备。 NUUO NVRMini2 3.0.8及之前版本中存在后门调试文件。远程攻击者可通过向后门文件handle_site_config.php发送特定的请求利用该漏洞执行任意命令。 1.Fofa搜索语句&#xff1a; 在Fofa网站&#xff0c;搜索&…

PyQt6实例_批量下载pdf工具_exe使用方法

目录 前置&#xff1a; 工具使用方法&#xff1a; step one 获取工具 step two 安装 step three 使用 step four 卸载 链接 前置&#xff1a; 1 批量下载pdf工具是基于博文 python_巨潮年报pdf下载-CSDN博客 &#xff0c;将这个需求创建成界面应用&#xff0c;达到可…

matlab 模拟 闪烁体探测器全能峰

clc;clear;close all %% 参数设置 num_events 1e5; % 模拟事件数 E 662e3; % γ射线能量&#xff08;eV&#xff09; Y 38000; % 光产额&#xff08;photon/MeV&#xff0c;NaI(Tl)&#xff09; eta 0.2; % 量子效率 G 1e6; …

启扬RK3568开发板已成功适配OpenHarmony4.0版本

启扬智能IAC-RK3568-Kit开发板支持Debian、Android等常见开源操作系统&#xff0c;目前已完成OpenHarmony4.0开源国产操作系统的适配工作&#xff0c;满足国产化开源操作系统客户的需求。 启扬智能IAC-RK3568-Kit开发板基于瑞芯微RK3568处理器设计&#xff0c;主频最高可达2.0G…

蓝桥与力扣刷题(蓝桥 山)

题目&#xff1a;这天小明正在学数数。 他突然发现有些止整数的形状像一挫 “山”, 比㓚 123565321、145541123565321、145541, 它 们左右对称 (回文) 且数位上的数字先单调不减, 后单调不增。 小朋数了衣久也没有数完, 他惒让你告诉他在区间 [2022,2022222022] 中有 多少个数…

WinDbg. From A to Z! 笔记(一)

原文链接: WinDbg. From A to Z! 文章目录 为什么使用WinDbg为什么通过本书学习底层原理简述Windows的调试工具一览dbghelp.dll -- Windows 调试助手dbgeng.dll -- 调试引擎接口 调试符号 (Debug Symbols)有哪些调试信息生成调试信息匹配调试信息调用堆栈 侵入式与非侵入式异常…

Axure RP 9.0教程: 基于动态面板的元件跟随来实现【音量滑块】

文章目录 引言I 音量滑块的实现步骤添加底层边框添加覆盖层基于覆盖层创建动态面板添加滑块按钮设置滑块拖动效果引言 音量滑块在播放器类APP应用场景相对较广,例如调节视频的亮度、声音等等。 I 音量滑块的实现步骤 添加底层边框 在画布中添加一个矩形框:500 x 32,圆…

Eclipse IDE for ModusToolbox™ 3.4环境通过JLINK调试CYT4BB

使用JLINK在Eclipse IDE for ModusToolbox™ 3.4环境下调试CYT4BB&#xff0c;配置是难点。总结一下在IDE中配置JLINK调试中遇到的坑&#xff0c;以及如何一步一步解决遇到的问题。 1. JFLASH能够正常下载程序 首先要保证通过JFLASH(我使用的J-Flash V7.88c版本)能够通过JLIN…

黑马点评项目

遇到问题&#xff1a; 登录流程 session->JWT->SpringSession->tokenRedis &#xff08;不需要改进为SpringSession&#xff0c;token更广泛&#xff0c;移动端或者前后端分离都可以用&#xff09; SpringSession配置为redis模式后&#xff0c;redis相当于分布式se…

wgcloud怎么实现服务器或者主机的远程关机、重启操作吗

可以&#xff0c;WGCLOUD的指令下发模块可以实现远程关机和重启 使用指令下发模块&#xff0c;重启主机&#xff0c;远程关机&#xff0c;重启agent程序- WGCLOUD

深度解析Spring Boot可执行JAR的构建与启动机制

一、Spring Boot应用打包架构演进 1.1 传统JAR包与Fat JAR对比 传统Java应用的JAR包在依赖管理上存在明显短板&#xff0c;依赖项需要单独配置classpath。Spring Boot创新的Fat JAR&#xff08;又称Uber JAR&#xff09;解决方案通过spring-boot-maven-plugin插件实现了"…

deepseek(2)——deepseek 关键技术

1 Multi-Head Latent Attention (MLA) MLA的核心在于通过低秩联合压缩来减少注意力键&#xff08;keys&#xff09;和值&#xff08;values&#xff09;在推理过程中的缓存&#xff0c;从而提高推理效率&#xff1a; c t K V W D K V h t c_t^{KV} W^{DKV}h_t ctKV​WDKVht​…

突破反爬困境:SDK架构设计,为什么选择独立服务模式(四)

声明 本文所讨论的内容及技术均纯属学术交流与技术研究目的&#xff0c;旨在探讨和总结互联网数据流动、前后端技术架构及安全防御中的技术演进。文中提及的各类技术手段和策略均仅供技术人员在合法与合规的前提下进行研究、学习与防御测试之用。 作者不支持亦不鼓励任何未经授…

自然语言处理,能否成为人工智能与人类语言完美交互的答案?

自然语言处理&#xff08;NLP&#xff09;作为人工智能关键领域&#xff0c;正深刻改变着人机交互模式。其发展历经从早期基于规则与统计&#xff0c;到如今借深度学习实现飞跃的历程。NLP 涵盖分词、词性标注、语义理解等多元基础任务&#xff0c;运用传统机器学习与前沿深度学…

蓝桥杯备考:八皇后问题

八皇后的意思是&#xff0c;每行只能有一个&#xff0c;每个对角线只能有一个&#xff0c;每一列只能有一个&#xff0c;我们可以dfs遍历每种情况&#xff0c;每行填一个&#xff0c;通过对角线和列的限制来进行剪枝 话不多说&#xff0c;我们来实现一下代码 #include <ios…

HDR(HDR10/ HLG),SDR

以下是HDR&#xff08;HDR10/HLG&#xff09;和SDR的详细解释&#xff1a; 1. SDR&#xff08;Standard Dynamic Range&#xff0c;标准动态范围&#xff09; • 定义&#xff1a;SDR是传统的动态范围标准&#xff0c;主要用于8位色深的视频显示&#xff0c;动态范围较窄&…

【MySQL】验证账户权限

在用户进行验证之后&#xff0c;MySQL将提出以下问题验证账户权限&#xff1a; 1.谁是当前用户&#xff1f; 2.该用户有何权限&#xff1f; 管理权限比如&#xff1a;shutdown、replication slave、load data infile。数据权限比如&#xff1a;select、insert、update、dele…

通过TIM+DMA Burst 实现STM32输出变频且不同脉冲数量的PWM波形

Burst介绍&#xff1a; DMA控制器可以生成单次传输或增量突发传输&#xff0c;传输的节拍数为4、8或16。 为了确保数据一致性&#xff0c;构成突发传输的每组传输都是不可分割的&#xff1a;AHB传输被锁定&#xff0c;AHB总线矩阵的仲裁器在突发传输序列期间不会撤销DMA主设备…

GaussDB数据库表设计与性能优化实践

GaussDB分布式数据库表设计与性能优化实践 引言 在金融、电信、物联网等大数据场景下&#xff0c;GaussDB作为华为推出的高性能分布式数据库&#xff0c;凭借其创新的架构设计和智能优化能力&#xff0c;已成为企业核心业务系统的重要选择。本文深入探讨GaussDB分布式架构下的…