2021暑假训练(1)二分

二分算法

在有序数组中,把目标值与中间值相比较,若不相等则不断更新中间值,将比较的区间逐渐变小,最后找到目标值的所在位置,时间复杂度为log2n。

eg:https://www.luogu.com.cn/problem/P2249

不断更新中间值,可以用递归也可以用while。

while:

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

 

 

 

递归:

int search(int l,int r,int key){
    int mid=l+r>>1;
    if(l==r){
        if(a[l]==key)
        return mid;
        else
        return -1;
    }
    if(key<=a[mid]){
        search(l,mid,key);
    }
    else{
        search(mid+1,r,key);
    }
}

完整代码(递归:

#include<stdio.h>
int a[1000000],b[100000];
int search(int l,int r,int key){
    int mid=l+r>>1;
    if(l==r){
        if(a[l]==key)
        return mid;
        else
        return -1;
    }
    if(key<=a[mid]){
        search(l,mid,key);
    }
    else{
        search(mid+1,r,key);
    }
}
int main()
{
    int n,m;
    scanf("%d%d",&n,&m);
    for(int i=1;i<=n;i++){
        scanf("%d",&a[i]);
    }
    for(int j=1;j<=m;j++){
        scanf("%d",&b[j]);
        printf("%d ",search(1,n,b[j]));
    }
    return 0;
}

(while:

#include<stdio.h>

const int N = 1e6 + 10;
int a[N];
int n,m;

int search(int k) {
    int l = 1, r = n;
    while(l < r) {
        int mid = l + r >> 1;
        if(a[mid] >= a[k]) {
            r = mid;
        }
        else
        l = mid + 1;
    }
    if(a[l] == k)
    return l;
    else
    return -1;
}
int main()
{
    int q;
    scanf("%d %d",&n,&m);
    for(int i = 1; i <= n; ++i)
        scanf("%d",&a[i]);
    for(int i = 1; i <= m; ++i) {
        scanf("%d",&q);
        printf("%d ",search(q));
    }
    return 0;
}

 

题单:http://www.mangata.ltd/2021/07/03/2021%e5%b9%b4swpuacm%e6%9a%91%e5%81%87%e9%9b%86%e8%ae%adday1%e4%ba%8c%e5%88%86%e7%ae%97%e6%b3%95/

 

哦,还可以直接用STLbound做,直接

int ans = lower_bound(a + 1, a + n + 1, x) - a;

 

就没了。

 

posted @ 2021-07-19 14:13  Untergehen  阅读(61)  评论(0编辑  收藏  举报