描述
输入n(n≤10……6)个不超过10……9的单调不减的(就是后面的数字不小于前面的数字)非负整数a1,a2…,an,然后进行m(m≤10……5)次询问。对于每次询问,给出一个整数q(q≤10^9),要求输出这个数字在序列中第一次出现的编号,如果没有找到的话输出 -1 。
输入
第一行 2 个整数 n 和 m,表示数字个数和询问次数。
第二行 n 个整数,表示这些待查询的数字。
第三行 m 个整数,表示询问这些数字的编号,从 1 开始编号。
输出
m 个整数表示答案。
输入样例1
11 3 1 3 3 3 5 7 9 11 13 15 15 1 3 6
输出样例1
1 2 -1
看到题,刷刷刷3分钟写完,结果……
错误代码
#include<bits/stdc++.h>
using namespace std;
int a[10000000];
int main()
{
int n,m;
cin>>n>>m;
for(int i=1;i<=n;i++)
cin>>a[i];
for(int j=1;j<=m;j++)
{
int shu,b=0;
cin>>shu;
for(int i=1;i<=n;i++)
if(shu==a[i])
{
cout<<i<<" ";
b=1;
break;
}
else if(shu<a[i])
{
cout<<-1<<" ";
b=1;
break;
}
if(b==0)
cout<<-1<<" ";
}
return 0;
}
很明显,超时了。
本题目应该用二分来写
AC代码
#include<bits/stdc++.h>
using namespace std;
int a[1000010];
int main(){
int n, m, i;
cin>>n>>m;
for(i=1; i<=n; i++) cin>>a[i];
for(i=1; i<=m; i++){
int q, j;
cin>>q;
//二分查找
int z=1, y=n, ans;
while(z<=y){//[z, y]范围
int mid=(z+y)/2;//二分
if(a[mid]>=q){//找第一个大于等于q的位置
ans=mid;//更新结果值
y=mid-1;//更新右边界
}else{
z=mid+1;//更新左边界
}
}
if(a[ans]==q) cout<<ans<<" ";
else cout<<-1<<" ";
}
return 0;
}
更简单一点,直接上函数
#include<bits/stdc++.h>
using namespace std;
int b[1000010];
int main(){
int n,m,i,shu;
cin>>n>>m;
for(i=0;i<n;i++){
cin>>b[i];
}
for(i=1;i<=m;i++){
cin>>shu;
int pos=lower_bound(b,b+n,shu)-b;
if(b[pos]==shu){
cout<<pos+1<<" ";
}else{
cout<<"-1"<<" ";
}
}
return 0;
}