突发奇想练二分板子
二分具体思想就是一直找有序序列的中点值并将其与查找值相比,若比查找值大就说明查找值在序列左半段,反之则在右半段。
具体细节见代码:
#include <iostream>
using namespace std;
int A[1000005]; int n,m,a;
int chazhao(int t){
int i=0,j=n-1,p=-2;
while(i<=j){//二分查找
int mid=(i+j)>>1;
if(A[mid]>a){
j=mid-1; continue;
}
if(A[mid]<a){
i=mid+1; continue;
}
if(A[mid]==a){
p=mid; break;
}
}
if(p!=-2){
while(A[p]==A[p-1]){//查看p是否是所求最小下标
if(p==0) break;//特例,若所求值为0时下标肯减到负值
p--;
}
return p;
}
return p;
}
int main(){
cin>>n>>m;
for(int i=0;i<n;i++) cin>>A[i];
for(int i=0;i<m;i++){
cin>>a;
cout<<chazhao(a)+1<<" ";
}
}
stl里面还有一对兄弟函数lower bound (返回大于或等于查找值的第一个数的指针)upper bound(返回大于查找值的第一个数的指针) ,注意他俩的区别。
具体见代码:
#include <iostream>
#include <vector>
using namespace std;
vector<int> A; int n,m,a;
int main(){
cin>>n>>m;
for(int i=0;i<n;i++) {
int b; cin>>b; A.push_back(b);
}
for(int i=0;i<m;i++){
cin>>a;
int t=lower_bound(A.begin(),A.end(),a)-A.begin();//特别注意要减去A的地址
if(A[t]!=a) cout<<-1<<" ";
else cout<<t+1<<" ";
}
}
题目出处:(https://www.luogu.com.cn/problem/P2249)