二分练习(SDUTOJ2781)

作为一道二分法的模板题,有必要插个眼;

二分练习

Description

给你一个序列,然后给你m个元素,让你从序列中找出与每个元素最接近的数字输出来,如果有两个就输出两个。
 

Input

 多组输入,第一行给你两个数n(0 < n < 10000000),m(0 < m < n),接下来是数列的n个数,然后再输入m个元素,让你找出最接近每个元素的值。如果有两个,按从小到大输出。
 

Output

 这m个数分别输出最接近每个元素的值,组与组之间输出一个空行。

Sample

Input 
8 4
1 2 3 4 5 6 8 11
4
9
2
7
Output 
4
8
2
6 8

Hint

 
Submit Solutions Topics
Time Limit1000 ms
Mem. Limit65536 KiB
Sourcelwn

本题可以用二分法完成,也可以用lower_bound完成;本质也是二分,不过不用手动实现

#include <bits/stdc++.h>
using namespace std;
int a[10000009];
int main()
{
    ios::sync_with_stdio(false);
    int n,m;double c;
    while(cin>>n>>m){
        for(int i=1;i<=n;++i){
            cin>>a[i];
        }
        sort(a+1,a+1+n);
        while(m--){
            cin>>c;if(a[n]<=c){cout<<a[n]<<endl;}
            else if(a[1]>=c)cout<<a[1]<<endl;
            else {
            int t=(lower_bound(a+1,a+1+n,c)-a);
            int k=t-1;
            int x=abs(a[t]-c),y=abs(c-a[k]);
            if(x==y)cout<<a[k]<<' '<<a[t]<<endl;
            else if(x>y)cout<<a[k]<<endl;
            else cout<<a[t]<<endl;
            }
        }
        cout<<endl;
    }
    return 0;
}

该做法的思路差不多就是先排序,然后用lower_bound 函数一下找出来大于等于目标值的第一个数;没什么要讲的地方。

第二种便是手动二分法了;

#include <bits/stdc++.h>
using namespace std;
int a[10000009];
int down(int l,int r,int n){
    int c=-1;
    while(l<=r){
        int k = (l+r)/2;
        if(a[k]<=n){
            c=k;
            l=k+1;
        }
        else r=k-1;
    }
    return c;
}
int up(int l,int r,int n){
    int c=-1;
    while(l<=r){
        int k=(l+r)/2;
        if(a[k]>=n){
            r=k-1;
            c=k;
        }
        else l=k+1;
    }
    return c;
}
int main()
{   ios::sync_with_stdio(false);
    cin.tie(0);cout.tie(0);
    int n,m;
    while(cin>>n>>m){
        for(int i=1;i<=n;++i){
            cin>>a[i];
        }
        sort(a+1,a+1+n);
        while(m--){
            int t;
            cin>>t;
            int x=down(1,n,t),y=up(1,n,t);
            if(x==-1)cout<<a[y]<<endl;
            else if(y==-1)cout<<a[x]<<endl;
            else if(a[x]==a[y])cout<<a[x]<<endl;
            else {
                int p=abs(t-a[x]),q=abs(a[y]-t);
                if(p==q)cout<<a[x]<<' '<<a[y]<<endl;
                else if(p>q)cout<<a[y]<<endl;
                else cout<<a[x]<<endl;
            }
        }cout<<endl;
    }
    return 0;
}

该方法的思想就是先找下界,然后再找上界,具体函数实现是取其中间值,若该中间值小于等于n的话,那么左边界变为mid+1,函数值变为mid;由mid小于等于n这个条件来确定函数值(down函数)up同理

要说的就是这么多,理清思路做题。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
湖南大学的头歌"python二分查找"是在计算机科学领域中一个非常常见而重要的算法二分查找也被称为是折半查找,它通过将查找区间逐步缩小至目标元素所在的区间来快速找到目标元素。 二分查找的基本思想是:假设在一个有序数组中要查找某个元素,首先确定数组的中间元素,如果中间元素等于待查找元素,则查找成功;如果中间元素大于待查找元素,则在中间元素的左半部分继续进行查找;如果中间元素小于待查找元素,则在中间元素的右半部分继续进行查找。每次比较后,都能将待查找区间缩小一半。通过不断地缩小查找区间,最终可以找到目标元素。 在Python中使用二分查找算法可以快速定位有序列表中的目标元素,减少了遍历整个列表的时间复杂度,提升了查找效率。这在处理大规模数据时尤为重要,因为二分查找的时间复杂度是O(log n),可以在很短的时间内找到目标元素。 湖南大学的学生们通过学习和掌握"python二分查找",可以更好地理解和运用这个经典的算法。这样的学习不仅能提高他们的算法思维能力,也能为他们今后的编程工作和科研研究奠定坚实的基础。通过实际编程练习,湖南大学的学生们可以掌握如何实现二分查找算法,并加深对算法原理的理解。 总之,湖南大学头歌"python二分查找"是一首经典的歌曲,它向我们展示了二分查找算法的精妙之处。通过学习和运用这个算法,可以提高解决问题的效率和准确性,为学生们今后的学习和研究生涯打下坚实的基础。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值