一、整数二分
Demo
Explain
- 将模板分为二种情况,循环以
l=r
结束 - 看第一段,若,因为是单增序列,推出 mid 后面的数会更大,所以缩小区间为左半段,又 mid 也可能是答案,因此
r=mid
- 为什么采用右移运算,而不是除法。右移是向下取整,整除是向零取整,在值域包含负数的时候后者没法正常工作。
Code
-
在单增序列 a 中查找中最小的那个
1 2 3 4 5 6
while l<r: mid=l+r>>1 if a[mid]>=x: r=mid else: l=mid+1
-
在 a 中找中最大的那个
1 2 3 4 5 6
while l<r: mid=l+r+1>>1 if a[mid]<=x: l=mid else: r=mid-1
E1 数的范围
topic
- 给定一个按照升序排列的长度为 n 的整数数组,以及 q 个查询。对于每个查询,返回一个元素 k 的起始位置和终止位置(位置从 0 开始计数)。如果数组中不存在该元素,则返回 -1 -1.
analyse
- 先用模板找起始位置,即最小的那个。
- 如果
s[l]!=x
,说明没找到,输出-1 -1
即可, - 否则,输出起始,再用模板找终止位置即可。
code
|
|
二、实数二分
Demo
Explain
- 确定精度
eps
.如果需要保留 k 位小数,
Code
|
|
E1 数的三次方根
题目
给定一个浮点数 n,求它的三次方根。
code
|
|
三、二分答案转换成判定
Explain
- 题目中出现类似于“最大值最小”的含义,这是答案具有单调性,可用二分转化成判定的特征之一
E1 最佳牛围栏
思考
- 转换题目:给定正整数数列 A,求一个平均数最大且长度不小于 L 的连续子段.
- 如果 mid 是答案,判定“是否存在一个长度不小于 L 的子段,平均数不小于二分的值”
- 如果每个数都减去 mid,那么就转化为,“是否存在一个长度不小于 L 的子段,子段和>=0”
- 如果存在,则更新
l=mid
,因为答案肯定在右边
code
|
|
E2 防线
思考
code
|
|