题目
给定一个 按照升序排列 大小随机排列的长度为 n 的整数数组,以及 m 个查询。
对于每个查询,返回一个元素 k 的起始位置和终止位置(位置从 0 开始计数)。
如果数组中不存在该元素,则返回 -1 -1
。
输入格式
第一行包含整数 n 和 m,表示数组长度和询问个数。
第二行包含 n 个整数(均在 1∼10000范围内),表示完整数组。
接下来 m 行,每行包含一个整数 k,表示一个询问元素。
输出格式
共 m 行,每行包含两个整数,表示所求元素的起始位置和终止位置。
如果数组中不存在该元素,则返回 -1 -1
。
数据范围
1≤ n ≤100000
1≤ m ≤10000
1≤ k ≤10000
输入样例:
6 3
1 2 2 3 3 4
3
4
5
输出样例:
3 4
5 5
-1 -1
代码实现如下:
#define _CRT_SECURE_NO_DEPRECATE
#include<cstdio>
#include<iostream>
using namespace std;
const int N = 100010;
int n,m,q[N],s[N];
void quick_sort(int s[],int l,int r) //快排不解释,有疑问详见之前发的模板
{
if(l>=r) return ;
int x=s[l+r>>1],i=l-1,j=r+1;
while(i<j)
{
do i++; while(x>s[i]);
do j--; while(x<s[j]);
if(i<j) swap(s[i],s[j]);
}
quick_sort(s,l,j);
quick_sort(s,j+1,r);
}
int main()
{
scanf("%d%d", &n, &m); //输入总数n和m个查询
for(int i=0;i<n;i++) scanf("%d",&q[i]);//输入长度为n的无序数组
quick_sort(q,0,n-1); //对无序数组进行排序
while (m -- ) //当m=0时判为假,退出循环
{
int x; //x表示要查询的元素
scanf("%d",&x);
int l=0,r=n-1; //左右两个指针
while(l<r) //判断边界,二分进行条件
{
int mid=l+r>>1; //找集合左边界(即元素初始位置),中点直接下取整即可
if(q[mid]>=x) r=mid; //若查询元素在中点左侧,更新右边界为mid,注意等号
else l=mid+1; //不满足,则更新左边界为mid+1
}
if(q[l]!=x) cout<<"-1 -1"<<endl;//若二分查找查无此元素,按要求输出"-1 -1"
else{ //以下是查到有效元素继续进行的操作
cout<<l<<" "; //输出元素x的起始位置,此时l == mid == x
int l=0,r=n-1; //初始化指针,继续查找右边界(即元素结束位置)
while(l<r) //与二分查找集合左边界不同
{
int mid=l+r+1>>1; //中点上取整
if(q[mid]<=x) l=mid; //查询元素在中点右侧,更新左边界为mid
else r=mid-1; //否则更新右边界为mid-1
}
cout<<l<<endl; //输出查询元素结束位置
}
}
return 0;
}