【题解】T6843 麦粒商店

原题链接

算法分析

此题末尾的数据范围很明显告诉我们顺序查找是拿不了满分的,而题目里又保证了输入的麦粒数为升序序列,这时使用二分查找就能很好地提高效率。顺序查找的时间复杂度为O(n),而二分查找的时间复杂度为O(log2n)。所谓二分查找,就是每次取数列正中间的数与要查找的数比较,如果比要查找的数大,就继续在左半边查找,反之则在右半边查找,查找的方法仍像这样,找到这个数就退出循环,因此二分查找又称作折半查找,前提是查找的序列为有序序列。本题则是两次使用二分查找每位顾客所需麦粒的左边界和右边界,最后用 右边界 - 左边界 求出每位顾客的麦粒总数。

示例代码

#include <cstdio>
int n, m, v[1000001], ans[1000001], x, y, l, r, first, last, mid, c = 1;//v数组用来存现有的麦粒,ans数组存答案
int main()
{
    scanf ( "%d%d", &n, &m );//输入n和m
    for ( int i = 1 ; i <= n ; i++ )
    scanf ( "%d", &v[i] );//输入现有麦粒
    for ( int i = 1; i <= m; i++ )//n位顾客循环
    {
        scanf ( "%d%d", &x, &y );//每次输入麦粒范围
        l = 0 , r = n , y++; //l为最左边,r为最右边,都是数组下标,为了使没有查到刚好落在y的左边,y需要+1
        while ( l <= r )//第一次查找左边界
        {
            mid = ( l + r ) >> 1;//mid为正中间的数,即(l+r)/2,这是位运算写法
            if ( v[mid] < x ) l = mid + 1 , first = mid;//查找右半部分,first为左边界
            else r = mid - 1;//查找右半部分
        }
        l = 0 , r = n;//赋回原来的值 
        while ( l <= r )//第二次查找右边界
        {
            mid = ( l + r ) >> 1;//取中值
            if ( v[mid] < y ) l = mid + 1 , last = mid;//同理,last为右边界
            else r = mid - 1;
        }
        ans[c++] = last - first;//右边界 - 左边界,答案存进ans数组
    }
    for ( int i = 1; i < c; i++ )
    printf ( "%d\n", ans[i] );//输出答案
    return 0;
}


  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值