二分

二分查找

在序列中寻找查找一个符合的元素通常为 \(O(n)\),即一次暴力枚举.在保证元素单调情况下,可以使用二分以“查字典”的方式一半一半地筛去不符合的元素,以 \(O(\log n)\) 的速度查找一个元素,也可以求解包括但不限于:单调递增递减的函数(如一次函数),插入排序二分优化.

(传统的 \(mid=(l+r+(k))>>1\) 可能带来负数溢出,可进一步改为 \(mid=(l\land r)+((l\oplus r)>>1)\)从而避免)

整数模板一

找大于等于该数的第一个数

int find_high(int x){    
	int l=1,r=n,mid;  
	  while (l < r){  
		mid = (l&r)+((l^r)>>1);  
		if (a[mid]>=x)  r = mid;      
		else l = mid + 1;  
	}
	return a[l];  
};  

整数模板二

找小于等于该数的第一个数

int find_low(int x){  
	int l=1,r=n,mid;  
	    while (l < r){    
		mid = (l&r)+((l^r)>>1)+1;  
		if (a[mid]<=x)  l = mid;  
		else r = mid - 1;  
	}
	return a[l];  
};  

实数模板

大于等于的第一个数

int find_high(double x){  
	int l=1,r=n,mid;  
	  while (r>l+esp){  
		mid = (l&r)+((l^r)>>1);  
		if (a[mid]>=x)  r = mid;  
		else l=mid+1;  
	}
	return a[l];
};

小于等于的第一个数

int find_low(double x){
	int l=1,r=n,mid;
	while (r>l+esp){
		mid = (l&r)+((l^r)>>1)+1;
		if (a[mid]<=x)  l = mid;
		else r = mid - 1;
	}
	return a[l];
};

二分答案

当题目求最大(小)可行的条件时,当参数与返回值成正相关或负相关时可以使用二分答案求解。

例题河中跳房子解:

求最短跳跃距离,由题意可得跳跃距离 \(l\in [1,L]\),由于 \(L\le 10^9\),在贪心超时,剪枝较困难时,采取二分,策略为以 \(1\) 为左边界, \(L\) 为右边界,二分枚举,复杂度 \(O(N\log_2 L)\approx O(30N)\)

posted @ 2025-08-20 20:55  badn  阅读(16)  评论(0)    收藏  举报