题目内容
给定一个按照升序排列的长度为n的整数数组,以及 q 个查询。
对于每个查询,返回一个元素k的起始位置和终止位置(位置从0开始计数)。
如果数组中不存在该元素,则返回“-1 -1”。
输入格式
第一行包含整数n和q,表示数组长度和询问个数。
第二行包含n个整数(均在1~10000范围内),表示完整数组。
接下来q行,每行包含一个整数k,表示一个询问元素。
输出格式
共q行,每行包含两个整数,表示所求元素的起始位置和终止位置。
如果数组中不存在该元素,则返回“-1 -1”。
数据范围
1≤n≤100000
1≤q≤10000
1≤k≤10000
输入样例
6 3
1 2 2 3 3 4
3
4
5
输出样例
3 4
5 5
-1 -1
题解
本题采用整数二分查找的思想求解。
首先,二分查找可以根据某个具体的性质,将某个区间切分为两部分,一部分满足性质,另一部分不满足性质,那么二分查找是可以找到其满足性质的边界点,这是二分查找的核心本质。因此,二分查找,就是求根据某个性质而产生的边界点。
那么,我们可以有如下思考,这里给出一张图,根据图来进行说明。
L和R代表序列的左右边界,黄色区间和红色区间是按照是否满足某个性质而产生的两段,若求黄色和红色的分界点,且设置黄色区间不满足分界性质,红色区间满足分界性质,思考如下:
- 当求黄色部分的分界点时:
- 假设mid=(L+R+1)/2,check函数为判断某个点是否满足黄色区间的性质,返回true或false。( 这里mid的定义(L+R+1)/2中的+1是避免出现死循环,具体可以思考当l=r-1时,若不加上1,就会出现死循环 )
- 若check(mid)为true,则说明,mid这个点满足条件,因此,分界点一定在其右边,因此接下来需要二分的区间应该是[mid,r],将l=mid;若check(mid)为false,则说明,mid这个点不满足条件,因此分界点一定在其左边,因此接下来需要二分的区间应该是[l,mid-1],r=mid-1。
- 当求红色部分的分界点时:
- 假设mid=(L+R)/2, check函数为判断某个点是否满足红色区间的性质,返回true或false。
- 若check(mid)为true,则说明,mid这个点满足这个性质,因此分界点应该在mid点的左边即二分的区间应该是[l,mid],r=mid;若check(mid)为false,则说明,mid这个点不满足这个性质,因此分界点应该在mid点的右边,即二分的区间应该是[mid+1,r],l=mid+1。
回到题中,我们可以进行如下思考:
因为题目中求某个数的范围,因此,边界有两个,一个是大于等于x,一个是小于等于x,对每个性质分别使用二分查找的方法求出分界点即可。
代码
|