洛谷笔记 - P2249 【深基 13. 例 1】查找

练点基础。

关于 “二分查找”

二分查找(英语:binary search),也称折半搜索(英语:half-interval search)、对数搜索(英语:logarithmic search),是用来在一个有序数组中查找某一元素的算法。

折半查找的前提是数组中的数据已经进行了排序。

利用数组已排序的特性,从数组的中间开始搜寻,如果这个数小于所搜寻的数,则该数左边的数一定都小于要搜寻的对象,所以无需浪费时间在左边的数中搜寻,直接搜寻右边的数;如果搜寻的数大于所搜寻的对象,则右边的数无需再搜寻,直接搜寻左边的数。如此类推,直到找到该元素,如果找不到则返回 - 1。

题目描述

输入 nn 个不超过 10910^9 的单调不减的(就是后面的数字不小于前面的数字)非负整数 a1,a2,,ana_1,a_2,\dots,a_{n},然后进行 mm 次询问。对于每次询问,给出一个整数 qq,要求输出这个数字在序列中第一次出现的编号,如果没有找到的话输出 1-1

输入格式

第一行 22 个整数 nnmm,表示数字个数和询问次数。

第二行 nn 个整数,表示这些待查询的数字。

第三行 mm 个整数,表示询问这些数字的编号,从 11 开始编号。

输出格式

输出一行,mm 个整数,以空格隔开,表示答案。

样例 #1

样例输入 #1

1
2
3
11 3
1 3 3 3 5 7 9 11 13 15 15
1 3 6

样例输出 #1

1
1 2 -1

提示

数据保证,1n1061 \leq n \leq 10^60ai,q1090 \leq a_i,q \leq 10^91m1051 \leq m \leq 10^5

本题输入输出量较大,请使用较快的 IO 方式。

代码

一个需要注意的点

题面上特别强调了一点:本题输入输出量较大,请使用较快的 IO 方式,所以本题的代码内主要使用 scanf()printf() 函数,用法详见 scanf ()/printf () 的输出用格式参数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
// 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");
}
}