藍橋杯高頻考點——二分(含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.pswp.cn/bicheng/74698.shtml
繁體地址,請注明出處:http://hk.pswp.cn/bicheng/74698.shtml
英文地址,請注明出處:http://en.pswp.cn/bicheng/74698.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

【谷粒商城踩坑記】第五坑 拖拽組件三級菜單拖不了問題

第五坑 拖拽組件三級菜單拖不了問題 直接進入或刷新頁面后,拖動第三級菜單項,無法修改排序位置&#xff0c;我嘗試了直接用源碼包中提供的老師的代碼也不行&#xff0c;本身就有這個小 Bug &#xff0c;或者說是其它什么地方有問題。 原始內容是這樣的。 countNodeLevel(node){…

《深度剖析Android 12 SystemUI鎖屏通知布局亮屏流程:從源碼到實現》

優化后文章結構&#xff1a; 1. 前言 強調鎖屏通知布局的重要性及分析目的&#xff0c;引出后續源碼分析的必要性。 2. 核心類解析 KeyguardViewMediator&#xff1a;鎖屏核心邏輯控制&#xff0c;處理亮屏/息屏事件分發。 PhoneWindowManager&#xff1a;系統輸入事件&…

Android系統的安全問題 - Android的keymaster和gatekeeper

Android 的 Keymaster 和 Gatekeeper 是兩大關鍵安全組件,分別負責硬件級別的密鑰管理和設備解鎖認證。它們在 Android 的安全架構中扮演重要角色,尤其在支持 硬件級安全特性(如可信執行環境 TEE 或專用安全芯片)的設備上。以下是它們的詳細對比和功能解析: 1. Keymaster(…

springBoot中雪花算術法

在 Spring Boot 中&#xff0c;雪花算法&#xff08;Snowflake Algorithm&#xff09;通常指的是 Twitter 開發的一種分布式唯一 ID 生成算法。它被廣泛用于分布式系統中生成全局唯一的 ID&#xff0c;尤其是在高并發場景下。雪花算法生成的 ID 是一個 64 位的長整型數字&#…

鴻蒙開發之ArkTS聯合類型

在鴻蒙開發中&#xff0c;ArkTS是一種基于TypeScript的編程語言&#xff0c;專為鴻蒙應用開發而設計。聯合類型&#xff08;Union Types&#xff09;在ArkTS中是一個重要的概念&#xff0c;它允許一個變量存儲多種類型的數據&#xff0c;從而增加了代碼的靈活性&#xff0c;同時…

K8S學習之基礎五十五:k8s中jenkins部署blueOcean

jenkins部署blueOcean 安裝插件 BLUE OCEAN 之后會多出一個菜單&#xff0c;可以更詳細方便的查看pipeline流程

DeepSeek概述

一、DeepSeek概述 1.1 DeepSeek是什么 DeepSeek是一家專注 通用人工智能&#xff08;AGI&#xff0c;Artificial General Intelligence&#xff09;的中國科技公司&#xff0c;主攻大數據研發與應用。DeepSeek-R1是其開源的推理模型&#xff0c;擅長處理復雜任務且可免費商用…

學習記錄(14):iOS部署

時隔多年后&#xff0c;再次部署開發iOS&#x1f601;&#x1f601; 1. Unity端設置&#xff0c;在此不再進行贅述&#xff08;網上一大堆&#xff09; 2. ??&#xff1a;要保證mac比待部署的設備版本要高 3. Xcode: (1) 打開從 Unity 3D 里打包的文件中&#xff0c;找到有…

如何使用DeepSeek編寫測試用例?

一、DeepSeek在測試用例設計中的定位 DeepSeek作為AI工具,并非直接替代測試設計,而是通過以下方式提升效率: 快速生成基礎用例框架(等價類、邊界值等) 智能補充易遺漏場景(如特殊字符、異常流) 自動化腳本片段生成(Python/pytest/JUnit等) 測試數據構造建議(符合業務…

9.4分漏洞!Next.js Middleware鑒權繞過漏洞安全風險通告

今日&#xff0c;亞信安全CERT監控到安全社區研究人員發布安全通告&#xff0c;Next.js 存在一個授權繞過漏洞&#xff0c;編號為 CVE-2025-29927。攻擊者可能通過發送精心構造的 x-middleware-subrequest 請求頭繞過中間件安全控制&#xff0c;從而在未授權的情況下訪問受保護…

【前端】原生項目與框架項目區別

不定期更新&#xff0c;建議關注收藏點贊。 使用 HTML CSS JS 和 Vue 或 React 開發的項目各有其優勢與不足&#xff0c;適用于不同的場景。目前基本上都采用框架&#xff0c; 總結 何時選擇 HTML CSS JS&#xff1a; 適用于 小型項目、簡單靜態頁面、不需要復雜交互 或 …

WinSCP使用教程:(SFTP、SCP、FTP 和 WebDAV)

WinSCP 是一款免費開源的 Windows 環境下的 SFTP、SCP、FTP 和 WebDAV 客戶端&#xff0c;主要用于在本地計算機與遠程服務器之間安全地傳輸文件&#xff0c;并提供基本的文件管理功能。 WinSCP是Windows環境下使用SSH的開源圖形化的SFTP的客戶端 SSH 的全稱是 Secure Shell&…

分布式鎖實戰:Redis與Redisson的深度解析

一、分布式鎖的必要性 在分布式系統中&#xff0c;當多個節點需要對共享資源進行讀寫操作時&#xff0c;傳統的本地鎖&#xff08;如Java的synchronized或ReentrantLock&#xff09;無法跨節點生效。此時&#xff0c;必須引入分布式鎖來保證操作的原子性和一致性。分布式鎖需滿…

Dify本地安裝部署筆記

目錄 方式一【docker安裝】&#xff1a; 步驟 1&#xff1a;準備工作 步驟2: 克隆dify倉庫 步驟3:部署啟動dify 步驟 4&#xff1a;訪問 Dify 步驟5:升級dify 方式二【源碼安裝】&#xff1a; 步驟1. 硬件&#xff1a;最低安裝要求 步驟2: 業務服務前的3個服務 1. 安…

質檢LIMS系統在食品生產加工企業的應用 如何保證食品生產企業的安全

在食品生產加工領域&#xff0c;質量安全是貫穿全產業鏈的生命線。隨著《食品安全法》對全過程追溯要求的深化&#xff0c;傳統實驗室管理模式已難以滿足高效、精準的質量管控需求。質檢實驗室信息管理系統&#xff08;LIMS&#xff09;作為數字化升級的核心工具&#xff0c;正…

自動駕駛VLA模型技術解析與模型設計

1.前言 2025年被稱為“VLA上車元年”&#xff0c;以視覺語言動作模型&#xff08;Vision-Language-Action Model, VLA&#xff09;為核心的技術范式正在重塑智能駕駛行業。VLA不僅融合了視覺語言模型&#xff08;VLM&#xff09;的感知能力和端到端模型的決策能力&#xff0c;…

UDP套接字編程(代碼)

什么是socket套接字編程&#xff1f; 通過Ip地址 端口號這種方式定位一臺主機&#xff0c;這樣的方式我們就叫做socket套接字。 Udp Socket 接口介紹 這些案列我們使用的接口基本都是一樣的&#xff0c;所以在這里我先把接口介紹完&#xff0c;具體的細節后面在說明。 創…

汽車行業可信數據空間研究探索

近期&#xff0c;相關老師在新能源汽車國家大數據聯盟微課堂發表了題為“汽車行業可信數據空間研究探索”的演講&#xff0c;主要包括可信數據空間的概念內涵、汽車行業可信數據空間的發展現狀、數據流通場景和技術需求研究、汽車行業可信數據空間的場景建設建議四個方面展開。…

圓弧插補相關算法匯總(C++和ST源代碼)

運動控制需要了解相關的插補概念,在閱讀本篇博客之前需要了解相關的準備知識,常用鏈接如下: SMART PLC直線插補詳解-CSDN博客文章瀏覽閱讀2.1k次,點贊2次,收藏4次。本文介紹了SMART PLC中軸組對象的概念,詳細講解了直線插補的原理和指令使用,包括SMART PLC從V2.7版本開…

Entity Framework框架

深入理解C#中的Entity Framework框架&#xff1a;從理論到實踐 在C#開發中&#xff0c;與數據庫交互是幾乎所有應用程序的核心需求之一。Entity Framework (EF) 作為微軟官方推出的ORM框架&#xff0c;極大地簡化了數據庫操作。本文將帶您深入理解EF框架的核心概念&#xff0c…