二分答案

本文介绍了二分搜索的基本原理及多种应用场景,包括查找值、最大化最小值、最小化最大值等,并提供了具体实现代码示例。
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] xi=1kw[i] 0∑i=1kv[i] −x∗∑i=1kw[i] ≥0

i=1kv[i] i=1kxw[i] 0∑i=1kv[i] −∑i=1kx∗w[i] ≥0

i=1kv[i]kw[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.其他的一些
  • 有可能二分的不是明显地表示上面的某个模型,这时候就要推导一发。(也有可能就不是上面的某个模型?)

  • 是不是二分要理智判断。似乎又是一句废话。问题的解一般要单调。

  • 有时候还会有一些恶心的二分套二分什么的。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值