题目
给定一个严格单调的数列,询问若干个数分别需要在数列中二分几次才能找到。如果能找到,输出二分的次数;如果不能找到,输出 NONE
。二分查找参考程序如下:
(数列单调递增时)
l = 1, r = n, cnt = 0;
while (l <= r) {
mid = (l + r) / 2;
cnt++;
if (a[mid] == key) break;
if (a[mid] > key) r = mid - 1;
else l = mid + 1;
}
(数列单调递减时)
l = 1, r = n, cnt = 0;
while (l <= r) {
mid = (l + r) / 2;
cnt++;
if (a[mid] == key) break;
if (a[mid] > key) l = mid + 1;
else r = mid - 1;
}
上述程序中结束时 cnt 的值即为二分次数。
输入格式
第一行两个整数 n,m 分别表示数列长度和询问次数。
第二行 n个整数,第 i 个表示 ai。
接下来 m 行,每行一个整数x 表示要求询问的数。
输出格式
共 m 行,如果能找到,输出二分的次数;如果不能找到,输出 NONE
。
提示:
读入/出数据量较大,请使用 scanf/printf
。
在函数声明或定义中,函数返回类型前加上关键字 inline
,即可以把函数指定为内联函数。这样可以解决一些频繁调用的函数大量消耗栈空间(栈内存)的问题,也能在一定程度上减少函数反复调用时消耗的时间。
Sample 1
Inputcopy | Outputcopy |
---|---|
10 4 1 2 3 5 7 9 11 12 13 14 7 6 5 4 | 1 NONE 4 NONE |
对于 %100 的数据:1<=n<= 10^6,1<= m<= 5*10^6,1<=x,ai<= 10^6
思路:
本题对于%100的数据范围若进行直接模拟,在询问时进行二分查找则时间复杂度会达到m*nlogn,会爆时间,而看到ai的数据范围,我们可以考虑用预处理的办法,存储每一个数要查询的次数,最后在询问时只需要直接输出none或者次数即可。
代码
#include<bits/stdc++.h>
#include<cstdlib>
using namespace std;
int a[1000010],b[1000010]={0};
int n;
int cnt=0;
inline void search1(int l,int r){//二分预处理函数
if(l>r)return;
int mid = (l + r) / 2;
cnt++;
b[a[mid]]=cnt;
search1(l,mid-1);//左端二分
search1(mid+1,r);//右端二分
cnt--;
return;
}
int main(){
freopen("A.in","r",stdin);
freopen("A.out","w",stdout);
int m,result;
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++)scanf("%d",&a[i]);
search1(1,n);
while(m--){
int key;
scanf("%d",&key);
if(b[key]==0)printf("NONE\n");
else printf("%d\n",b[key]);
}
return 0;
}