题目描述
给定一个按照升序排列的长度为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
二分
第一篇二分搜索论文是 1946 年发表,然而第一个没有 bug 的二分查找法却是在 1962 年才出现,中间用了 16 年的时间。
——不知道哪里看的
整数二分
yxc二分模板
二分的本质是二段性不是单调性。
当想找不满足性质的边界值(红色区域的右边界值)
- 找中间值
mid = (l+r+1)/2
- if(check(mid))等于true或者是false
check(m)是检查m是在不满足性质的区间(检查是不是在红色区间) - 更新l或者r
当想找满足性质的边界值(绿色区域的左边界值)
1. 找中间值 mid = (l+r)/2
2. if(check(mid))等于true或者是false
check(m)是检查m是在满足性质的区间(检查是不是在绿色区间)
3. 更新l或者r
归结上面的两种二分方法,步骤为:
- 先写一个check函数
- 判定在check的情况下(true和false的情况下),如何更新区间。
- 在check(m)==true的分支下是:
l=mid
的情况,中间点的更新方式是m=(l+r+1)/2
r=mid
的情况,中间点的更新方式是m=(l+r)/2
这种方法保证了:
1. 最后的l==r
2. 搜索到达的答案是闭区间的,即a[l]是满足check()条件的。
模板
//#define judge
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn = 1e5 + 10;
int n, q, k;
int a[maxn];
int main() {
#ifndef judge
freopen("in.txt", "r", stdin);
freopen("out.txt", "w", stdout);
#endif
scanf("%d%d", &n, &q);
for (int i = 0; i < n; i++) {
scanf("%d", &a[i]);
}
for (int i = 0; i < q; i++) {
scanf("%d", &k);
int l = 0, r = n - 1;
while (l < r) {
int mid = l + r >> 1;
if (a[mid] >= k) {
r = mid; //第二种情况 找绿色区间的左端点
} else {
l = mid + 1;
}
}
if (a[l] != k) {
printf("-1 -1\n");
} else {
printf("%d ", l);
l = 0, r = n - 1;
while (l < r) {
int mid = l + r + 1 >> 1;
if (a[mid] <= k) {//第一种情况 找红色区间的右端点
l = mid;
} else {
r = mid - 1;
}
}
printf("%d\n",l);
}
}
return 0;
}
一些其他细节
为什么需要+1?
原因是如果不加上1,那么mid
得到的是下取整的数,那么有可能[m,r]更新过后m会一直等于m(m+1==r的情况)会陷入死循环。
https://blog.csdn.net/WJPnb1/article/details/126360962?spm=1001.2014.3001.5502
这篇blog写的好,不用考虑mid-1和mid+1的边界问题
那这个找不到的时候怎么判断呢
最后返回了一个数组不存在的下标,当然就是找不到了。
dd大佬 可以补个图吗 想了解的更加直观
图图不见了
图片看不了了、
本地图片要怎么上传呀
这不比大段大段文字管用!!!!?太厉害了!!!!!!!!
为什么先判断找绿色区间的左端点,而不是先找红色区间的右端点呢
大佬,请问二分的本质是二段性是怎么理解的
大佬,请问二分的本质是二段性是怎么理解的
?
这个写的真的好!!!
orz
很有帮助!!!感谢!!!orz
谢谢,有点收获了
是分界点,是找分界点!是逼近分界点!
666
大佬借个图!!
细
精辟
### 六六六