zoukankan      html  css  js  c++  java
  • lower_bound和upper_bound的用法

    本篇文章同步发表于 luogu-blog

    两个函数用于 升序 降序 非递减序列(升序带并列),非递增序列(降序带并列)

    这两个函数都是STL自带的二分查找函数,具有优秀的时间复杂度(O(logn))

    在头文件<algorithm>内,不过lower_bound不用<algorithm>好像不会报错。(逃~)

    函数原型

    _ForwardIterator lower_bound(_ForwardIterator _first,_ForwardIterator _last,const _Tp&__val)
    _ForwardIterator upper_bound(_ForwardIterator _first,_ForwardIterator _last,const _Tp&__val)
    

    升序(带并列)

    lower_bound()upper_bound()默认在升序序列中进行二分查找,不需要添加参数。

    lower_bound()在一个升序序列中,返回一个指向大于等于该元素的第一个迭代器。

    如果没有大于等于该元素的元素,返回指向最后一位元素的后一位的迭代器,即last,注意last是越界的!

    #include<cstdio>
    #include<iostream>
    #define LL long long
    using namespace std;
    int num[]={0,1,1,2,3,6,7,9,15,17,21,32,48}; //升序 
    const int n=12;
    int main()
    {
    	cout<<num[(lower_bound(num+1,num+n+1,8)-num)]<<endl; //result : 9
    	//两种写法相同 
    	cout<<*lower_bound(num+1,num+n+1,0)<<endl; //result : 1
    	cout<<*lower_bound(num+1,num+n+1,1)<<endl; //result : 1
    	cout<<*lower_bound(num+1,num+n+1,2)<<endl; //result : 2
    	cout<<*lower_bound(num+1,num+n+1,3)<<endl; //result : 3
    	cout<<*lower_bound(num+1,num+n+1,4)<<endl; //result : 6
    	cout<<*lower_bound(num+1,num+n+1,5)<<endl; //result : 6
    	cout<<*lower_bound(num+1,num+n+1,6)<<endl; //result : 6
    	cout<<*lower_bound(num+1,num+n+1,7)<<endl; //result : 7
    	cout<<*lower_bound(num+1,num+n+1,8)<<endl; //result : 9
    	cout<<*lower_bound(num+1,num+n+1,9)<<endl; //result : 9
    	cout<<*lower_bound(num+1,num+n+1,10)<<endl; //result : 15
    	cout<<*lower_bound(num+1,num+n+1,15)<<endl; //result : 15
    	cout<<*lower_bound(num+1,num+n+1,17)<<endl; //result : 17
    	cout<<*lower_bound(num+1,num+n+1,22)<<endl; //result : 32
    	cout<<*lower_bound(num+1,num+n+1,49)<<endl; //result : 0
    	if(lower_bound(num+1,num+n+1,49)==num+n+1) 
    		puts("lower_bound(num+1,num+n+1,49)==num+n+1"); 
    			//result:lower_bound(num+1,num+n+1,49)==num+n+1
    	//lower_bound()在一个升序序列中,返回一个指向大于等于该元素的第一个迭代器。 
    	//如果没有大于等于该元素的元素,返回指向最后一位元素的后一位的迭代器; 
    	return 0;
    }
    

    upper_bound()在一个升序序列中,返回一个指向大于该元素的第一个迭代器。

    如果没有大于该元素的元素,返回指向最后一位元素的后一位的迭代器;

    #include<cstdio>
    #include<iostream>
    #include<algorithm>
    #define LL long long
    using namespace std;
    int num[]={0,1,1,2,3,6,7,9,15,17,21,32,48}; //升序 
    const int n=12;
    int main()
    {
    	cout<<num[upper_bound(num+1,num+n+1,8)-num]<<endl; //result :9
    	//两种写法相同
    	cout<<*upper_bound(num+1,num+n+1,0)<<endl;  //result :1
    	cout<<*upper_bound(num+1,num+n+1,1)<<endl;  //result :2
    	cout<<*upper_bound(num+1,num+n+1,2)<<endl;  //result :3
    	cout<<*upper_bound(num+1,num+n+1,3)<<endl;  //result :6
    	cout<<*upper_bound(num+1,num+n+1,4)<<endl;  //result :6
    	cout<<*upper_bound(num+1,num+n+1,5)<<endl;  //result :6
    	cout<<*upper_bound(num+1,num+n+1,6)<<endl;  //result :7
    	cout<<*upper_bound(num+1,num+n+1,7)<<endl;  //result :9
    	cout<<*upper_bound(num+1,num+n+1,8)<<endl;  //result :9
    	cout<<*upper_bound(num+1,num+n+1,9)<<endl;  //result :15
    	cout<<*upper_bound(num+1,num+n+1,16)<<endl;  //result :17
    	cout<<*upper_bound(num+1,num+n+1,25)<<endl;  //result :32
    	cout<<*upper_bound(num+1,num+n+1,32)<<endl;  //result :48
    	cout<<*upper_bound(num+1,num+n+1,49)<<endl;  //result :0
    	if(upper_bound(num+1,num+n+1,48)==num+n+1) 
    		puts("upper_bound(num+1,num+n+1,48)==num+n+1");
    			//result:upper_bound(num+1,num+n+1,48)==num+n+1
    	//upper_bound()在一个升序序列中,返回一个指向大于该元素的第一个迭代器。 
    	//如果没有大于该元素的元素,返回指向最后一位元素的后一位的迭代器; 
    	return 0;
    }
    

    降序(带并列)

    降序查找需要加一个参数。

    比如在int类型的降序数列里查找。

    bool cmp(const int &a,const int &b)
    {
    	return a>b;
    }
    

    类似sort

    在升序内用小于号,降序内用大于号。

    感性理解:就是前一个数和后一个数的关系啦。。

    lower_bound(num,num+n,1,cmp)
    

    当然也可以用STL自带的greater

    lower_bound(num,num+n,1,greater<int>())
    

    其他与升序一样。

    upper_bound()lower_bound()一样。

    #include<cstdio>
    #include<iostream>
    #include<algorithm>
    #define LL long long
    using namespace std;
    int num[]={48,32,21,17,15,9,7,6,3,2,1,1}; //降序 
    const int n=12;
    bool cmp(const int &a,const int &b)
    {
    	return a>b;
    }
    int main()
    {
    	freopen(".out","w",stdout);
    	cout<<*lower_bound(num,num+n,1,greater<int>())<<endl;
    	cout<<*lower_bound(num,num+n,1,greater<int>())<<endl;
    	cout<<*lower_bound(num,num+n,2,greater<int>())<<endl;
    	cout<<*lower_bound(num,num+n,3,greater<int>())<<endl;
    	cout<<*lower_bound(num,num+n,4,greater<int>())<<endl; 
    	cout<<*lower_bound(num,num+n,5,greater<int>())<<endl;
    	cout<<*lower_bound(num,num+n,6,greater<int>())<<endl; 
    	cout<<*lower_bound(num,num+n,7,greater<int>())<<endl;
    	cout<<*lower_bound(num,num+n,8,greater<int>())<<endl;
    	cout<<*lower_bound(num,num+n,9,greater<int>())<<endl; 
    	cout<<*lower_bound(num,num+n,10,greater<int>())<<endl;
    	cout<<*lower_bound(num,num+n,15,greater<int>())<<endl; 
    	cout<<*lower_bound(num,num+n,17,greater<int>())<<endl; 
    	cout<<*lower_bound(num,num+n,22,greater<int>())<<endl; 
    	cout<<*lower_bound(num,num+n,49,greater<int>())<<endl;  
    	return 0;
    }
    

    (result)

    1
    1
    2
    3
    3
    3
    6
    7
    7
    9
    9
    15
    17
    21
    48
    

    结构体

    竟然加入了可供(DIY)的参数,那就可以在一个结构体数组内实现二分查找了!

    #include<cstdio>
    #include<iostream>
    #include<algorithm>
    #define LL long long
    using namespace std;
    struct student
    {
    	int mark;
    	int num;
    };
    student a[20];
    bool cmp(const student &a,const student &b)
    {
    	return a.mark>b.mark;
    }
    int main()
    {
    	a[0]=student{100,0};
    	a[1]=student{89,1};
    	a[2]=student{89,2};
    	a[3]=student{79,3};
    	a[4]=student{69,4};
    	a[5]=student{59,5};
    	a[6]=student{49,6};
    	a[7]=student{39,7};
    	a[8]=student{29,8};
    	a[9]=student{19,9};
    	a[10]=student{9,10};
    	student b={67,9};
    	cout<<lower_bound(a,a+10,b,cmp)->mark<<endl;
    	return 0;
    }
    

    (result)

    59
    

    特别鸣谢:热心网友之江学院石洗凡老师的帮助

  • 相关阅读:
    Java安全之对称加密、非对称加密、数字签名
    Java 设计模式 之 中介者模式(Mediator)
    使用jquery获取radio的值
    java6枚举类型
    java http头信息
    怎样用java生成GUID与UUID
    struts2国际化
    JSON.stringify(),JSON.parse(),toJSON()方法使用
    阻塞队列之六:LinkedBlockingDeque
    jQuery给控件赋值....
  • 原文地址:https://www.cnblogs.com/cjl-world/p/13490928.html
Copyright © 2011-2022 走看看