zoukankan      html  css  js  c++  java
  • 二分查找

    题目描述

    总时间限制: 15000ms 单个测试点时间限制: 5000ms 内存限制: 228000kB
    描述
    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 .
    输入
    The first line of the input file contains the size of the lists n (this value can be as large as 4000). We then have n lines containing four integer values (with absolute value as large as 228 ) that belong respectively to A, B, C and D .
    输出
    For each input file, your program has to write the number quadruplets whose sum is zero.
    样例输入
    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
    提示
    Sample Explanation: Indeed, the sum of the five following quadruplets is zero: (-45, -27, 42, 30), (26, 30, -10, -46), (-32, 22, 56, -46),(-32, 30, -75, 77), (-32, -54, 56, 30).

    解题分析

    保存前两列所有组合的和a[],保存后两列的所有组合的和b[],对b数组排序,对与a[]中每个数,在b中二分查找其相反数。
    注意在二分查找过程,需要在b中找到小于等于目标元素的最大值,如果这个最大值等于目标元素,再沿着数组向后找到相等的元素,计数即可。
    这里采用的查找区间用闭区间表示,当target <= b[mid],right = mid,当target > b[mid],left = mid + 1,这中区间判定策略保证了b[left]<= target <= b[right],并且当target == b[mid]的时候,能将right左移到第一个等于target的b数组元素。退出循环的条件是 left == right,此时,查找区间就只有一个元素这个元素要么等于target,要么小于target,那么它就是小于等于target的最大元素,从这个元素开始向后找就能找到所有和target相等的元素。
    通常我们使用的二分查找采用退出循环条件是left > right,因为在left == right,查找区间还有一个元素,但是不能判定这个元素一定就和目标元素相等,所以还需要一轮循环判定这个元素是否与目标元素相等。

    解题代码

    #include <cstdio>
    #include <algorithm>
    using namespace std;
    
    int a[4010], b[4010], c[4010], d[4010];
    int A[16000000], B[16000000];
    int main(){
        int n;
        int num = 0;
        while(scanf("%d", &n) != EOF){
            num = 0;
            for(int i = 0; i < n; i++){
                scanf("%d%d%d%d", a+i, b+i, c+i, d+i);
            }
            int m = 0;
            for(int i = 0; i < n; i++){
                for(int j = 0; j < n; j++){
                    A[m] = a[i] + b[j];
                    B[m] = c[i] + d[j];
                    m++;
                }
            }
            
            sort(B, B+m);
            
            for(int i = 0; i < m; i++){
                int target = -A[i];
                int l = 0, r = m - 1;
                int mid = l;
                while(l < r){
                    mid = l + (r - l)/2;
                    if(target <= B[mid])
                        r = mid;
                    else
                        l = mid + 1;
                }
                while(B[l] == target && l < m){
                    num++;
                    l++;
                }
            }
            printf("%d
    ", num);
            
        }
    }
    
  • 相关阅读:
    玩聚的互联网热点新发现 精度上升到了一个新高度
    玩聚热点新发现中国的techmeme
    个性化阅读的过去和未来【中】
    【职经分享】走出公司进入产业建立圈子
    玩聚Alpha版本上线运行
    产品路径经营者当局者迷
    个性化阅读的过去和未来【上】
    Web2.0人性驱动的事业和仿生学
    获得硬盘上文件 文件夹
    电脑上QQ出现“该页面暂时无法显示”解决办法!
  • 原文地址:https://www.cnblogs.com/zhangyue123/p/12744323.html
Copyright © 2011-2022 走看看