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; }
哦,还可以直接用STLbound做,直接
int ans = lower_bound(a + 1, a + n + 1, x) - a;
就没了。