题目描述
输入n个不超过10^9 的单调不减的(就是后面的数字不小于前面的数字)非负整数a1,a2,...,an,然后进行m次询问。对于每次询问,给出一个整数q,要求输出这个数字在序列中第一次出现的编号,如果没有找到的话输出-1 。
输入格式
第一行 2个整数n和m,表示数字个数和询问次数。
第二行n个整数,表示这些待查询的数字。
第三行m个整数,表示询问这些数字的编号,从 11 开始编号。
输出格式
输出一行,m个整数,以空格隔开,表示答案。
输入样例
11 3 1 3 3 3 5 7 9 11 13 15 15 1 3 6
输出样例
1 2 -1
说明/提示
数据保证,1 <= n <= 10^6,0 <= ai,q <= 10^9,1 <= m <= 10^5
本题输入输出量较大,请使用较快的 IO 方式。
注:虽然这里要使用较快的IO方式,但是不能通过getline(cin, str)而只能通过减少I/O次数(如Input与Processed一同进行),因为每位数字都算作一个字符,占用的长度难以确认
解题思路:
核心解题思路:二分搜索
以下为简单的二分搜索的实现
#include <iostream> using namespace std; int main() { int num_array[10] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }; int right = 9, left = 0, middle; int acquire; bool acquire_result = false; cin >> acquire; while (right >= left) { middle = (right + left) / 2; if (num_array[middle] == acquire) { acquire = true; break; } else if (num_array[middle] > acquire) { right = middle - 1; } else { left = middle + 1; } } if (acquire_result) { cout << "True" << endl; } else { cout << "False" << endl; } return 0; }
采用IPO思路实现代码:
(1)I:
创建两个数组,分别用于存储n个数字和m次询问的结果
用for循环输入n个数字
(2)P和O:
用for循环询问m次,每次得到的结果存储到数组中,统一输出
每次循环键入一个值,用二分法搜索
搜索到指定值以后,再次用while循环调用内层二分法,以确保得到最早出现的位置
代码实现如下:
#include <iostream> using namespace std; //考虑到边界条件,前后各留出一个冗余位 int num_array[int(1e6) + 1 + 1] = { -1 };//n个数字 int num_array_q[int(1e5) + 1] = { -1 };//m次询问结果 int main() { int n, m; int i, j, z, middle;//循环和二分控制符 int pos;//获取最早出现位置,若未搜索到,则为-1 std::cin.tie(nullptr); cin >> n >> m; for (i = 1; i <= n; i++)//循环输入n个数字 { cin >> num_array[i]; } for (z = 1; z <= m; z++)//循环进行m次询问 { cin >> num_array_q[z]; //二分搜索开始 i = 1, j = n, pos = -1; while (i <= j) { middle = (i + j) / 2; if (num_array[middle] == num_array_q[z]) { while (num_array_q[z] == num_array[middle - 1])//while循环条件:只要middle的左侧仍有相同元素,就继续二分查找 { int inner_j = middle - 1;//内层二分的右 int inner_middle;//内层二分的middle while (i <= inner_j) { inner_middle = (i + inner_j) / 2; if (num_array[inner_middle] == num_array_q[z]) { middle = inner_middle; break;//找到内层middle,赋值给外层middle,退出,进入下一轮内层二分 } else if (num_array[inner_middle] > num_array_q[z]) { inner_j = inner_middle - 1; } else { i = inner_middle + 1; } } } pos = middle; break; } else if (num_array[middle] > num_array_q[z]) { j = middle - 1; } else { i = middle + 1; } } cout << pos << ' '; } return 0; }