整数二分板子
整數二分板子
對于一個區間,給定一個性質, 一半區間(不一定等分)滿足這個性質,另一半區間不滿足這個性質,二分可以查找這個邊界。
找到右邊綠顏色的邊界點
step1:找中間值 mid=(l+r)/2
step2:if(check(mid)) 這里的是check一下mid是否滿足綠色這個性質,
如果check為true,說明mid滿足這個性質,則mid一定在右半邊區間內,則要找的答案在左邊區間 [l,mid]內,這里mid是閉區間。更新方式是r=mid
如果check為false ,則mid 位于左半部分,即紅色這個區間,此時正確答案在[mid+1,r ] ,更新方式:l=mid+1;
模板為
int bsearch_1(int l,int r){while(l<r){int mid=l+r>>1;if(check(mid)) r=mid;else l=mid+1;} }找到左邊紅色的邊界點
step1:找中間值 mid=(l+r)/2,注意這里要改,只是作為第一步思考的話,可以這樣寫。實際上寫到后面,這里需要寫成mid=(l+r+1)/2,當使用l=mid時,記得補上+1
step2:if(check(mid)) 這里的是check一下mid是否滿足紅色這個性質,
如果check為true,說明mid滿足這個性質,則mid一定在左半邊區間內,則要找的答案在 右邊區間[mid,r]內,這里mid是閉區間。更新方式是l=mid
如果check為false ,則mid 位于右半部分,即綠色這個區間,此時正確答案在[l,mid-1 ] ,更新方式:r=mid-1;
模板為
//區間[l,r]倍劃分為[l,mid-1]和[mid,r]時使用 int bsearch_2(int l, int r){while(l<r){int mid=l+r+1>>1;if(check(mid)) l=mid;else r=mid-1;}return 1; }找到右邊綠色的邊界點
數的范圍
模板題
數的范圍
給定一個按照升序排列的長度為n的整數數組,以及 q 個查詢。
對于每個查詢,返回一個元素k的起始位置和終止位置(位置從0開始計數)。
如果數組中不存在該元素,則返回“-1 -1”。
輸入格式
第一行包含整數n和q,表示數組長度和詢問個數。
第二行包含n個整數(均在1~10000范圍內),表示完整數組。
接下來q行,每行包含一個整數k,表示一個詢問元素。
輸出格式
共q行,每行包含兩個整數,表示所求元素的起始位置和終止位置。
如果數組中不存在該元素,則返回“-1 -1”。
數據范圍
1≤n≤100000
1≤q≤10000
1≤k≤10000
輸入樣例:
輸出樣例:
3 4 5 5 -1 -1分析:
第一個位置:一定是后面的元素都是大于等于它的,前面的元素都是小于它的。
最后一個位置:一定是前面的元素都是小于等于它的,后面的元素都是大于它的。
仍然需要提醒:當 l=mid時,需要保留+1,該邊界需要清除。
ac代碼
補充
upper_bound()函數,該函數返回第一個大于待查數的迭代器。
lower_bound()函數,返回第一個大于等于待查數的迭代器。
lower_bound()在區間中如果找不到一個數,可能返回end(),即數組中最后一個元素下標的下一個位置。同時也可能返回第一個大于該數的位置
比如在下面序列中要查找2,此時返回的是1,即第一個3的下標。
由于該特性,上題不能使用lower_bound等庫函數來做
會出現如下錯誤,附上錯誤代碼
錯誤代碼的輸出
輸入 6 3 1 3 3 4 4 6 2 8 3輸出 1 0//在查詢2時出現的問題 -1 -1 1 2 標準答案 -1 -1 -1 -1 1 2總結
- 上一篇: 如何避免家中的厨房水龙头堵塞?
- 下一篇: 签到题汇总