二分的一点小见解
作者:
hongye
,
2025-04-09 11:14:46
· 辽宁
,
所有人可见
,
阅读 4
1 2 2 3 3 4
假设要查询3这个数,要查找左端点,就查大于等于的条件,因为
0 0 0 1 1 1 可以看到大于等于的最左一个数,就是左端点
1 2 3 4 5 6
模拟一下代码
第一轮 l=1,r=6 mid=3 mid不满足条件 l=4;
第二轮 l=4,r=6 mid=5 mid满足条件 r=5 , ans=5;
第三轮 l=4 r=5 mid=4 mid满足条件 r=3 ans=4;
第四轮 l=4,r=3 不满足条件,退出。
可以看到我们是逐渐将区间缩小到一个数,只要在每次满足条件时更新答案就能得到边界
#include <iostream>
using namespace std;
const int N =100010;
int val[N];
int n , m;
int findleft(int x){
int l = 1 , r = n;
int ans = 0;
while(l <= r){
int mid = (l+r)>>1;
if(val[mid] >= x){
ans = mid;
r = mid-1;
}else{
l = mid+1;
}
}
return ans;
}
int findright(int x){
int l=1 , r=n;
int ans = 0;
while(l <= r){
int mid = (l+r)>>1;
if(val[mid] <= x){
ans = mid;
l = mid+1;
}else{
r = mid-1;
}
}
return ans;
}
int main(){
cin>>n>>m;
for(int i=1;i<=n;i++) cin>>val[i];
while(m--){
int l , r , x;
cin>>x;
l = findleft(x);
if(val[l] != x){
cout<<"-1 -1"<<endl;
}else{
cout<<l-1<<" "<<findright(x)-1<<endl;
}
}
return 0;
}