POJ 二分查詢 快速找到和為零的四個數
阿新 • • 發佈:2018-11-30
問題描述
定義求和問題如下:給定4組整數A,B,C,D,找到有多少四元組(a,b,c,d)∈A×B×C×D,滿足條件a+b+c+d=0。此問題中,假設A,B,C,D具有相同的大小n。
輸入資料
輸入包含多組測試資料。每組測試資料的第一行包含一個整數n,表示A,B,C,D的元素個數(n<=4000)。接下來n行每行4個整數,分別屬於A,B,C,D,每個整數的大小在-228~228之間。
輸出要求
對於每組測試資料,輸出滿足條件的四元組的個數。
輸入樣例
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
解題思路
將問題轉化為兩組整數的問題。首先枚舉出a、b兩組所有可能的和sum1,以及c、d兩組所有可能的和sum2,將這兩組和看成新的組數,然後根據給定兩組和為0,對於sum1中每一個數sum1[i],判斷-sum1[i]是否在sum2中。即問題轉化為查詢問題,可以使用二分查詢加快查詢速度。首先對sum1,sum2元素排序,從小到大列舉每一個元素sum1[i],使用二分查詢判斷-sum1[i]是否在陣列中,然後計算出現的次數。陣列中可能會出現相同的元素,所以採用變形的二分法,在有重複元素的陣列中返回小於或等於目標元素的最大元素,若返回元素等於目標元素,則沿著陣列計數該元素出現的次數。採用左右都是閉區間
程式碼
#include<iostream>
#include<algorithm>
using namespace std;
int Sum1[10000006],Sum2[10000006];
int a[4001],b[4001],c[4001],d[4001];
int t=0;
int FindCount(int target)
{
//二分查詢
int l=0,h=t-1,num=0;
while(l<h)
{
int mid=l+(h-l)/2;
if(target<=Sum2[mid]) //查詢重複元素
{
h=mid;
}
else
{
l=mid+1;
}
}
while(Sum2[l]==target&&l<t) //計算重複出現的次數
{
num++;
l++;
}
return num;
}
int main()
{
int n;
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++)
{
for(int j=0;j<n;j++)
{
Sum1[t]=a[i]+b[j];
Sum2[t]=c[i]+d[j];
t++;
}
}
sort(Sum1,Sum1+t);
sort(Sum2,Sum2+t);
int num=0;
for(int i=t-1;i>=0;i--)
{
num+=FindCount(-Sum1[i]);
}
cout<<num<<endl;
return 0;
}