比如a数组数据是
idx | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 |
---|---|---|---|---|---|---|---|---|---|---|---|
ele | 1 | 2 | 3 | 4 | 5 | 6 | 6 | 6 | 6 | 7 | 8 |
需要搜索的元素
t
a
r
g
e
t
=
6
target = 6
target=6
bsearch_1用于查找左边第一个
≥
t
a
r
g
e
t
\ge target
≥target的元素的下标,res_idx=5,(
m
i
d
=
l
+
r
>
>
1
的情况
mid = l+r>>1的情况
mid=l+r>>1的情况),如果
t
a
r
g
e
t
=
6
target = 6
target=6不存在,返回7元素下标9
bsearch_2用于查找左边第一个
≤
t
a
r
g
e
t
\le target
≤target的元素的下标,res_idx=8(
m
i
d
=
l
+
r
+
1
>
>
1
的情况
mid = l+r+1>>1的情况
mid=l+r+1>>1的情况),如果
t
a
r
g
e
t
=
6
target = 6
target=6不存在,返回5元素下标4
t a r g e t target target存在 | t a r g e t target target不存在 | |
---|---|---|
bsearch_1 | 查找左边第一个 ≥ t a r g e t \ge target ≥target的元素的下标,res_idx=5,( m i d = l + r > > 1 的情况 mid = l+r>>1的情况 mid=l+r>>1的情况) | 返回第一个 ≥ t a r g e t 的元素的下标 \ge target的元素的下标 ≥target的元素的下标 |
bsearch_2 | 查找左边第一个 ≤ t a r g e t \le target ≤target的元素的下标,res_idx=8( m i d = l + r + 1 > > 1 的情况 mid = l+r+1>>1的情况 mid=l+r+1>>1的情况) | 返回第一个 ≤ t a r g e t 的元素的下标 \le target的元素的下标 ≤target的元素的下标 |
二分模板
bool check(int x) {/* ... */} // 检查x是否满足某种性质
// 区间[l, r]被划分成[l, mid]和[mid + 1, r]时使用:
int bsearch_1(int l, int r)
{
while (l < r)
{
int mid = l + r >> 1;
if (a[mid]>=target) r = mid; // check()判断mid是否满足性质
else l = mid + 1;
}
return l;
}
// 区间[l, r]被划分成[l, mid - 1]和[mid, r]时使用:
int bsearch_2(int l, int r)
{
while (l < r)
{
int mid = l + r + 1 >> 1;
if (a[mid]<=target) l = mid;
else r = mid - 1;
}
return l;
}
#include<iostream>
using namespace std;
const int N=100086;
int a[N],n,q;
int main(){
cin>>n>>q;
for(int i=0;i<n;++i) cin>>a[i];
while(q--){
int k;
cin>>k;
int l=0,r=n;
while(l<r){
int mid=l+r>>1;
if(a[mid]>=k) r=mid;
else l=mid+1;
}
if(a[l]!=k)
{
cout<<"-1 -1"<<endl;
cout<<l<<"\n";
continue;
}
cout<<l;
l=0,r=n-1;
while(l<r){
int mid=l+r+1>>1;
if(a[mid]<=k) l=mid;
else r=mid-1;
}
cout<<" "<<r<<endl;
}
return 0;
}