题解思路
设要查找的区间左右分别为L,R。
二分查找的左右边界为l,r
要查找的值是k
第一次二分查找找的是L:
l=0,r=n;
循环条件 l<r
如果[mid]<k,l=mid+1;
如果[mid]>=k,r=mid; 目的是将l卡到k的最左边。
第二次二分查找找R:
l=l,r=n+1;
循环条件 l+1<r
如果[mid]<=k,l=mid;
如果[mid]>k,r=mid;目的是将l卡到k的最右边
eg:
0 1 2 3 4 5 6 7
1 2 3 3 3 4 5 5
AC代码:
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
#define in(x) scanf("%d",&x)
#define in64(x) scanf("%lld",&x)
#define debug(x) cerr<<#x<<" : "<<x<<endl
using namespace std;
int a[100005];
void find(int k,int n);
int main(){
int n,q;in(n);in(q);
for(int i=0;i<n;i++){
in(a[i]);
}
while(q--){
int k;in(k);
find(k,n);
}
return 0;
}
void find(int k,int n){
int l,r;
l=0,r=n-1;
while(l<r){
int mid=l+r>>1;
if(a[mid]<k){
l=mid+1;
}
else{
r=mid;
}
}
if(a[l]!=k){
cout<<"-1 -1\n";
return ;
}
else{
cout<<l;
}
r=n;
while(l+1<r){
int mid=l+r>>1;
if(a[mid]>k){
r=mid;
}
else {
l=mid;
}
}
cout<<" "<<l<<endl;
}