4 Values whose Sum is 0 POJ - 2785(二分查詢)
阿新 • • 發佈:2018-12-25
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 .
Input
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 2
28 ) that belong respectively to A, B, C and D .
Output
For each input file, your program has to write the number quadruplets whose sum is zero.
Sample Input
6 -45 22 42 -16 -41 -27 56 30 -36 53 -37 77 -36 30 -75 -46 26 -38 -10 62 -32 -54 -6 45Sample Output
5Hint 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).
題目大意:從四列中分別選一個數,問使所選的數加和為0,有多少種選法。
思路:暴力的話複雜度是n^4,肯定超時,用二分(個人認為叫折半列舉更合適)簡化的話,複雜度有所降低。這裡說下折半列舉,就是分別列舉計算第1、2行 和第3、4行的加和分別是sum1[i]、sum2[i],再通過列舉sum1[i],sum2[i]計算結果。 然而這樣仍然超時,這裡在查詢sum1,sum2時,我們是逐個列舉的,太耗時。下面介紹一個簡化複雜度的技巧:利用二分查詢。先對sum1、sum2排序,逐個列舉sum1裡的數,在sum2中查詢 存在幾個sum2=(-sum1)。這裡用到upper_bound和lower_bound查詢。
這裡:利用 函式 upper_bound 和lower_bound 的性質 upper_bound(sum1,sum1+n*n,-sum2[i])-lower_bound(sum1,sum1+n*n,-sum2[i]) 表示在sum1中查詢值等於(-sum2)的個數。
下面上程式碼:
#include<stdio.h> #include<iostream> #include <map> #include<set> #include<algorithm> #define inf 0x3f3f3f3f using namespace std; long long sum1[16100000],sum2[16100000],a[4100][4]; int main(){ int n,i,j; long long sum=0; scanf("%d",&n); for(i=0;i<n;i++){ scanf("%lld%lld%lld%lld",&a[i][0],&a[i][1],&a[i][2],&a[i][3]); } for(i=0;i<n;i++){ for(j=0;j<n;j++){ sum1[i*n+j]=a[i][0]+a[j][1]; sum2[i*n+j]=a[i][2]+a[j][3]; } } sort(sum1,sum1+n*n); //注意sum1、sum2的範圍是n*n sort(sum2, sum2+n*n); for(i=0;i<n*n;i++){ sum+=upper_bound(sum1,sum1+n*n,-sum2[i])-lower_bound(sum1,sum1+n*n,-sum2[i]); //在sum1中查詢 值等於(-sum2) 的個數 } printf("%lld\n",sum); return 0; }