数的范围

数的范围

给定一个按照升序排列的长度为 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

思路

  1. 整数二分
  2. lower_bound,upper_bound

Code

1. 整数二分

点击查看代码
#include<iostream>
using namespace std;
int n,q;
const int N = 1e5 + 10;
int a[N];
int main(){
	cin >> n >> q;
	for(int i = 0; i < n; i ++)cin >> a[i];
	
	while(q --){
		int x;
		cin >> x;
		int l = 0,r = n - 1;
		while(l < r){
			int mid = l + r >> 1;
			if(a[mid] >= x)r = mid;
			else l = mid + 1;
		}
		if(a[l] == x){
			cout << l << " ";
			r = n - 1;
			while(l < r){
				int mid = l + r + 1>> 1;		//l = mid时l+r+1>>1
				if(a[mid] <= x)l = mid;
				else r = mid - 1;
			}
			cout << r << endl;
		}
		else cout << "-1 -1" << endl;
	}
}

2. lower_bound,upper_bound

点击查看代码
#include<iostream>
using namespace std;
const int N = 1e5 + 10;
int a[N];

int main(){
	int n,q;
	cin >> n >> q;
	for(int i = 0; i < n; i ++)cin >> a[i];
	while(q --){
		int op;
		cin >> op;
		int l = lower_bound(a,a+n,op) - a,r = upper_bound(a,a+n,op) - a - 1;
		if(a[l] == op && a[r] == op)cout << l << " " << r << endl;
		else cout << "-1 -1"<< endl;
	}
	return 0;
}

注意:

  1. lower_bound( begin,end,num):从数组的begin位置到end-1(左闭右开)位置二分查找第一个大于或等于num的数字,找到返回该数字的地址不存在则返回end。通过返回的地址减去起始地址begin,得到找到数字在数组中的下标。
  2. upper_bound( begin,end,num):从数组的begin位置到end-1位置二分查找第一个大于num的数字,找到返回该数字的地址,不存在则返回end。通过返回的地址减去起始地址begin,得到找到数字在数组中的下标。
posted @ 2022-12-09 20:42  Keith-  阅读(101)  评论(0编辑  收藏  举报