#include<iostream>
#include<algorithm>
using namespace std;
const int N = 100010;
int n,k;
int p[N];
using namespace std;
// 二分的本质: 整数二分法
// 找到一个性质,这个性质可以吧区间分成两半
// | -----------------|←左 右→|---------------------|
// 既可以找到左边的边界又可以找到右边的边界
// ①mid =l+r+1/2 先判断是否符合左半边的性质
// ②先进行check(mid)的判断,if(true){ mid就在左半边,但是答案区间在[mid,r]}
// else{ mid就在右面这个性质上,因此mid在左面的区间上,答案就在[l,mid-1]}
// 为什么else语句将要进行mid-1,因为此时的mid并不符合左边区间的性质条件
// ③mid = l+r/2 然后判断是否符合右面区间的性质
// if(true)那么表明mid符合右半边的性质,因此mid在右区间,因此答案就在[l,mid]
// else { mid就在左半边的区域上,答案就在[mid+1,r]}
//分析为什么第一种情况的时候为什么还要在加上一个1,因为当mid=l+r/2,l=r-1的时候,那么mid=l,因此遍历的区间仍是[l,r]就会陷入
//到死循环的境地
int main(){
cin>>n>>k;
for(int i=0;i<n;i++){
scanf("%d",&p[i]);
}
while(k--){
int x;
cin>>x;
int l = 0,r=n-1;
while(l<r)
{
int mid = (l+r)>>1;//二进制往右移是除以二
if(p[mid]>=x)//寻找开始的节点,那么就应该覆盖右侧的重复的区域
r = mid;
else l = mid+1;
}
if(p[l]!=x)
cout<<"-1 -1"<<endl;
else{
cout<<l;
l= 0,r=n-1;
while(l<r){
int mid = (l+r+1)>>1;
if(p[mid]<=x)
l = mid;
else
r = mid-1;
}
cout<<" "<<l<<endl;
}
}
return 0;
}
789.数的范围
最新推荐文章于 2024-07-13 23:05:26 发布