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号
浙公网安备 33010602011771号