AcWing 789.数的范围(plus)

题目

给定一个  按照升序排列  大小随机排列的长度为 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;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

BlueCatの夏天

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值