二分答案 / 整体二分学习笔记

本讲内容分为两个部分;

第1部分:二分答案介绍

第2部分:整体二分介绍

Part 1 二分答案介绍

相信大家都对二分答案比较熟悉。

至少...需要会二分查找...

我们考虑对于决策单调的问题:

给出一个长度为$n$的递增数列,现在有$m$个询问,每个询问有一个参数$k_i$

对于每一个询问输出这个递增序列中的大于等于$k_i$的位置最靠前的项的位置。

如果没有输出$-1$

对于100%的数据$ n,m \leq 10^6$

这个就大概是二分查找的模板题了,我们当考虑的是当前搜区间是$[L,R]$

其中间项$M=\left \lfloor \frac{L+R}{2} \right \rfloor$大于还是小于$k_i$

如果严格$a_M \geq k_i$,那么搜$[L,M]$否则搜$[M+1,R]$

显然这段代码就可以干这件事情

# include <bits/stdc++.h>
using namespace std;
const int N=1e6+10;
int a[N],n,m;
int work(int k)
{
    int l=1,r=n,ans=-1;
    while (l<=r) {
        int m=(l+r)/2;
        if (a[m]>=k) r=m-1,ans=m;
        else l=m+1;
    }
    return ans;
}
int main()
{
    scanf("%d%d",&n,&m);
    for (int i=1;i<=n;i++) scanf("%d",&a[i]);
    while (m--) {
        int k; scanf("%d",&k);
        printf("%d\n",work(k));
    }
    return 0;
}
二分查找lower_bound()实现

不作赘述。

这里写图片描述

满足决策单调性的事情可以用二分答案转化为判定类问题。

给出二分答案模板:

int l=-inf,r=inf,ans;
while (l<=r) {
    int mid=(l+r)>>1;
    if (check(mid)) ans=mid,l=mid+1; //向更优解尝试
    else r=mid-1; //向更劣解尝试
}
return ans;

然而今天的重点不是这个,这个有点low

猜你喜欢

转载自www.cnblogs.com/ljc20020730/p/10424336.html
今日推荐