20251020 - 二分 总结
前言
按照以往惯例,今天不是 20251020 - 二分 & 分治吗?
二分
使用二分的原因
在有序数组或有单调性的题目中,可以使用二分查找/二分答案来优化枚举。
原理
每次指定一个区间,把他劈成两半,排除不合法的区域,重复执行直到得到答案。
写法:
方法零:
int erfen(int x){
int pos = lower_bound(a.begin(),a.end(),x)-a.begin();
return a[pos] == x ? pos : -1;
}
方法一:
int erfen(int x){
int l = Left_Interval - 1,r = Right_Interval + 1;
while(l + 1 < r){
int mid = (l + r) >> 1;
if(check(...)){
l = mid;
}else{
r = mid;
}
}
return a[r] == x ? pos : -1;
}
方法二:
int erfen(int x){
int l = Left_Interval,r = Right_Interval,ans = 0;
while(l <= r){
int mid = (l + r) >> 1;
if(check(...)){
l = mid + 1;
ans = mid
}else{
r = mid - 1;
// ans = mid
}
}
return a[ans] == x ? pos : -1;
}
方法三(不正经MZC):
int erfen(int x){
int l = Left_Interval - 1,r = Right_Interval;
while(l < r){
int mid = (l + r + 1) >> 1;
if(check(...)){
l = mid;
}else{
r = mid - 1;
}
}
return a[...] == x ? pos : -1;
}
二分答案
再有单调性的题目中,可以通过二分答案,把时间复杂度从 \(O(...n)\) 优化到 \(O(...log_2n)\)。
对于 \(n = 10^5\) 时,二分答案很有用!
例题:[跳石头](20251020 - 二分 - Virtual Judge)
想法一:暴力
枚举每一个最长间隔,在贪心判断是否可行!
想法二:二分答案
可以发现,当间隔越长,可以放的石头就越少,所以考虑二分答案!
void solve(){
scanf("%d%d%d",&l,&n,&m);
for(int i = 1;i <= n;i++)
scanf("%d",&a[i]);
a[++n] = l; // 至于为什么?T_T,最后一个石头跳到终点也可能跳不到,可惜了罚时了!
int l = -1,r = 1e9 + 1;
while(l + 1 < r){
int mid = (l + r) / 2;
if(check(mid))
l = mid;
else
r = mid;
}
printf("%d\n",l);
}

浙公网安备 33010602011771号