二分查找 - bailian 3441:4 Values whose Sum is 0
Posted zhangyue123
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了二分查找 - bailian 3441:4 Values whose Sum is 0相关的知识,希望对你有一定的参考价值。
题目描述
总时间限制: 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);
}
}
以上是关于二分查找 - bailian 3441:4 Values whose Sum is 0的主要内容,如果未能解决你的问题,请参考以下文章