练点基础。
关于“二分查找”
二分查找(英语:binary search),也称折半搜索(英语:half-interval search)、对数搜索(英语:logarithmic search),是用来在一个有序数组中查找某一元素的算法。
折半查找的前提是数组中的数据已经进行了排序。
利用数组已排序的特性,从数组的中间开始搜寻,如果这个数小于所搜寻的数,则该数左边的数一定都小于要搜寻的对象,所以无需浪费时间在左边的数中搜寻,直接搜寻右边的数;如果搜寻的数大于所搜寻的对象,则右边的数无需再搜寻,直接搜寻左边的数。如此类推,直到找到该元素,如果找不到则返回-1。
题目描述
输入 $n$ 个不超过 $10^9$ 的单调不减的(就是后面的数字不小于前面的数字)非负整数 $a_1,a_2,\dots,a_{n}$,然后进行 $m$ 次询问。对于每次询问,给出一个整数 $q$,要求输出这个数字在序列中第一次出现的编号,如果没有找到的话输出 $-1$ 。
输入格式
第一行 $2$ 个整数 $n$ 和 $m$,表示数字个数和询问次数。
第二行 $n$ 个整数,表示这些待查询的数字。
第三行 $m$ 个整数,表示询问这些数字的编号,从 $1$ 开始编号。
输出格式
输出一行,$m$ 个整数,以空格隔开,表示答案。
样例 #1
样例输入 #1
11 3
1 3 3 3 5 7 9 11 13 15 15
1 3 6
样例输出 #1
1 2 -1
提示
数据保证,$1 \leq n \leq 10^6$,$0 \leq a_i,q \leq 10^9$,$1 \leq m \leq 10^5$
本题输入输出量较大,请使用较快的 IO 方式。
代码
{% note %}
一个需要注意的点
题面上特别强调了一点:本题输入输出量较大,请使用较快的 IO 方式,所以本题的代码内主要使用scanf()与printf()函数,用法详见 scanf()/printf() 的输出用格式参数
{% endnote %}
// Problem: P2249 【深基13.例1】查找
// Contest: Luogu
// URL: https://www.luogu.com.cn/problem/P2249
// Memory Limit: 125 MB
// Time Limit: 1000 ms
//
// Powered by CP Editor (https://cpeditor.org)
#include<iostream>
int num[1000001];
int n,m;
int search(int target){
int left=1,right=n;
while(left<=right){
int mid=(left+right)/2;
if(num[mid]>=target){
right=mid-1;
}else left=mid+1;
}
return num[left]==target?left:-1;
}
int main(){
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++){
scanf("%d",&num[i]);
}
for(int i=1;i<=m;i++){
int tmp;
scanf("%d",&tmp);
if(tmp>=num[1]&&tmp<=num[n]){
printf("%d",search(tmp));
}else printf("-1");
if(i!=m){
printf(" ");
}else printf("\n");
}
}