two-point question

789. Range of Numbers

 

Given an array of integers of length n in ascending order, and q queries.

For each query, return the starting and ending positions of an element k (positions are counted from 0).

Returns "-1 -1" if the element does not exist in the array.

input format

The first line contains integers n and q, indicating the length of the array and the number of queries.

The second line contains n integers (all in the range 1 to 10000), representing the complete array.

The next q lines each contain an integer k representing a query element.

output format

There are q lines in total, and each line contains two integers, indicating the starting position and ending position of the element being sought.

Returns "-1 -1" if the element does not exist in the array.

data range

1≤n≤1000001≤n≤100000
1≤q≤100001≤q≤10000
1≤k≤100001≤k≤10000

Input sample:

6 3
1 2 2 3 3 4
3
4
5

Sample output:

3 4
5 5
-1 -1

 

It should be noted here that we need to find an interval in which the target value is located, so we can use the two-in-two dichotomous template to solve it;

The first is the maximum and minimum values, where the mid falls in the left interval, where the coordinates of the first target value are determined

The second is the maximum value of the minimum value. The mid here falls in the right interval. Here, the coordinates of the last target value are determined, and the interval should be increased by one.

Note that the first if condition is >=

Note that the second if condition is <=

Since our question is an ascending sequence, when we first look for the first target number, of course, the number we find is getting bigger and bigger, until the first number >= target value appears;

Similarly, when we look for the last target number, we look for it in descending order, using <=

 

 

#include<iostream>
#include<stdio.h>
using namespace std;
const int N = 1e6 + 10;
int a[N], n, k;

int main(){
	scanf("%d %d", &n, &k);
	for(int i = 0; i < n; i++){
		scanf("%d", &a[i]);
	}

	while(k--){
		int x;
		scanf("%d", &x);
		int l = 0, r = n - 1;  //确定二分区间 
		
		//一开始确定对应的左区间端点,也就是第一个大于等于目标值的数,最大的最小值
		//mid在左边的区间
		//此时无需加一
		while(l < r){
			int mid = l + r >> 1;
			if(a[mid] >= x)	r = mid;
			else l = mid + 1;
		}
		if(a[l] != x) cout << "-1 -1" << endl;  //没有找到
		
		//现在确定对应的右边区间的端点,也就是最后一个<=目标值的数,最小值最大
		//mid在右边的区间
		//此时区间要加一
		else{
			cout << l << " ";
			
			int  l = 0, r = n - 1;
			while(l < r){
				int mid = l + r + 1 >> 1;
				if(a[mid] <= x) l = mid;
				else r = mid - 1;   
			}
			
			cout << l << endl;
		}
		
		
	}
	return 0;
} 

 

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=326387109&siteId=291194637