0.定义
二分搜索法,是通过不断缩小解可能存在的范围,从而求得问题最优解的方法。
1.查找值
在一个有序的数组中查找一个值。
因为有序,所以可以二分。
这里就找了自己十几天前打的一个求有序序列的上界的代码。
大致是这样的:取出中间的数,如果大于要查找的值,答案就在左边,否则在右边。这样每次查找都可以把范围缩小一半。所以时间复杂度就是O(log n)了。
int LB(int A[],int n,int x)
{
int L=0,R=n;
while(L<R)
{
int mid=(L+R)/2;
if(A[mid]>=x) R=mid;
else L=mid+1;
}
return L;
}
2.最大化最小值
顾名思义,就是通过二分答案让最小值最大。好吧我承认这是句废话
如果中间值满足题意,那么最小值大于等于中间值。否则小于中间值。
int BS()
{
int lb=0,ub=l+1;
while(lb+1<ub)
{
int mid=(lb+ub)/2;
if(check(mid)) lb=mid;
else ub=mid;
}
return lb;
}
3.最小化最大值
类似上文。
int BS()
{
int lb=0,ub=INF;
while(lb+1<ub)
{
int mid=(lb+ub)/2;
if(check(mid)) ub=mid;
else lb=mid;
}
return ub;
}
4.最大化平均值
给定n个物品,有自己的重量和价值。选出k个物品,使平均价值最大。
虽然有些并不一定是二分但有些也确实是二分。到时候再确定是不是二分。
这里就把用二分做的题目所用的方法推导一下好了。
定义C(x):=可以选择使得单位重量的价值不小于x。
若C(x)可行,则
∑ki=1v[i] ∑ki=1w[i] ≥x∑i=1kv[i] ∑i=1kw[i] ≥x
则
∑i=1kv[i] −x∗∑i=1kw[i] ≥0∑i=1kv[i] −x∗∑i=1kw[i] ≥0
∑i=1kv[i] −∑i=1kx∗w[i] ≥0∑i=1kv[i] −∑i=1kx∗w[i] ≥0
∑i=1kv[i]−k∗w[i] ≥0∑i=1kv[i]−k∗w[i] ≥0
所以就可以用这个思路来二分答案了。
bool cmp(node p,node q) { return p.t>q.t; }
bool check(double x)
{
for(int i=1;i<=n;i++) a[i].t=a[i].a-a[i].b*x;
sort(a+1,a+n+1,cmp);
double ans=0;
for(int i=1;i<=n-k;i++) ans+=a[i].t;
return ans>=0;
}
double BS()
{
double lb=0.0,ub=1.0;
while(lb+eps<ub)
{
double mid=(lb+ub)/2;
if(check(mid)) lb=mid;
else ub=mid;
}
return lb;
}
5.其他的一些
有可能二分的不是明显地表示上面的某个模型,这时候就要推导一发。(也有可能就不是上面的某个模型?)
是不是二分要理智判断。
似乎又是一句废话。问题的解一般要单调。有时候还会有一些
恶心的二分套二分什么的。

本文介绍了二分搜索的基本原理及多种应用场景,包括查找值、最大化最小值、最小化最大值等,并提供了具体实现代码示例。
1040

被折叠的 条评论
为什么被折叠?



