zoukankan      html  css  js  c++  java
  • 【刷题记录】 && 【算法杂谈】折半枚举与upper_bound 和 lower_bound

    【什么是upper_bound 和 lower_bound】

    简单来说lower_bound就是你给他一个非递减数列[first,last)和x,它给你返回非递减序列[first, last)中的第一个大于等于值x的位置

    而upper_bound就是你给他一个非递减数列[first,last)和x,它给你返回非递减序列[first, last)中的第一个大于值x的位置

    STL中实现这两种函数的算法就是二分。。。。。。

    【upper_bound 和 lower_bound代码】

    //STl中的lower_bound源代码
    //这个算法中,first是最终要返回的位置
    int lower_bound(int *array, int size, int key)
    {
        int first = 0, middle;
        int half, len;
        len = size;
    
        while(len > 0) 
    	{
            half = len >> 1;
            middle = first + half;
            if(array[middle] < key) 
    		{     
                first = middle + 1;          
                len = len-half-1;   //在右边子序列中查找
            }
            else
                len = half;      //在左边子序列(包含middle)中查找
        }
        return first;
    }
    //——————————upper_bound——————————————————
    int upper_bound(int *array, int size, int key)
    {
        int first = 0, len = size-1;
        int half, middle;
    
        while(len > 0){
            half = len >> 1;
            middle = first + half;
            if(array[middle] > key)     //中位数大于key,在包含last的左半边序列中查找。
                len = half;
            else{
                first = middle + 1;    //中位数小于等于key,在右半边序列中查找。
                len = len - half - 1;
            }
        }
        return first;
    }
    //______________End___________________________________________________________
    

    【POJ 2785】

    【题目原文】

            The SUM problem can be formulated as follows: given four lists A, B, C, D of integer values, compute how many quadruplet (a, b, c, d ) ∈ A x B x C x D are such that a + b + c + d = 0 . In the following, we assume that all lists have the same size n .

    【题目大意】

            给定各有n个整数的4个数列A,B,C,D。要从每一个数列中各去出一个数,使四个数的和为0.求出这样组合的个数。(当同一数列中有相同数字时按不同数字看待——博主注)

    【输入描述】

            有n行,一行4个数,分别是A[i],B[i],C[i],D[i]

    【输入样例】

            

    6
    -45 22 42 -16
    -41 -27 56 30
    -36 53 -37 77
    -36 30 -75 -46
    26 -38 -10 62
    -32 -54 -6 45
    

    【输出描述】

            一个数

    【输出样例】

    5
    

    【博主注释】

            有5种情况,分别是-45-27+42+30    26+30-10-46    -32+22+56-46    -32+30-75+77    -32-54+56+36

    【题目分析】

            我们把这些数对半分成AB与CD考虑。先从AB中取出a[i],b[i]后,为了使总和为0则需要从CD中取出c[i]+d[i]=a[i]-d[i]。因此将这些情况枚举出来,再用upper_bound和lower_bound进行二分即可。时间复杂度为O(n^2 logn)

    【代码】

    #include<iostream>
    #include<cstdio>
    #include<algorithm>
    using namespace std;
    const int maxn=4001;
    int n;
    int a[maxn],b[maxn],c[maxn],d[maxn];
    int cd[16000001];
    int lower_bound(int *array, int size, int key)
    {
        int first = 0, middle;
        int half, len;
        len = size;
        while(len > 0) 
    	{
            half = len >> 1;
            middle = first + half;
            if(array[middle] < key) 
    		{     
                first = middle + 1;          
                len = len-half-1;   //在右边子序列中查  找
            }
            else
                len = half;      //在左边子序列(包含middle)中查找
        }
        return first;
    }
    int upper_bound(int *array, int size, int key)
    {
        int first = 0, len = size-1;
        int half, middle;
        while(len > 0)
    	{
            half = len >> 1;
            middle = first + half;
            if(array[middle] > key) len = half;    //中位数大于key,在包含last的左半边序列中查找.
            else
    		{
                first = middle + 1;    //中位数小于等于key,在右半边序列中查找。
                len = len - half - 1;
            }
        }
        return first;
    }
    int main()
    {
        cin>>n;
    	for(int i=0;i<n;i++) cin>>a[i]>>b[i]>>c[i]>>d[i];   
    	//for(int i=0;i<n;i++) cin>>b[i];   
    	//for(int i=0;i<n;i++) cin>>c[i];   
    	//for(int i=0;i<n;i++) cin>>d[i]; 
    	for(int i=0;i<n;i++)
    	{
            for(int j=0;j<n;j++) cd[i*n+j]=c[i]+d[j];
    	}  
    	sort(cd,cd+n*n);
    	long long res=0;
    	for(int i=0;i<n;i++)
    	{
            for(int j=0;j<n;j++)
            {
    	        int CD=-(a[i]+b[j]);
    	        res+=upper_bound(cd,cd+n*n,CD)-lower_bound(cd,cd+n*n,CD);
    		}
    	}
    	cout<<res;
    	return 0;
    }
    

      

  • 相关阅读:
    mybatis
    Enumeration接口
    oracle undo 解析(转载收藏)
    Windows下RabbitMQ的安装
    Aliyun服务器安装Docker
    Redis主从复制、哨兵模式
    Redis持久化-AOF
    Redis持久化-RDB
    Nginx快速上手
    有关Eureka的其他重点配置
  • 原文地址:https://www.cnblogs.com/lijiaxin-blog-cpp/p/6163904.html
Copyright © 2011-2022 走看看