题目:
给出4个n(1<=n<=4000)元素集合A,B,C,D,要求分别从中选取一个元素a,b,c,d使得a+b+c+d=0。
思路:
a+b=-(c+d)。
将(a+b)的和(c+d)的和全部枚举出来,然后枚举(a+b)的和利用二分查找c+d中符合的元素。
代码如下:
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <iostream>
using namespace std;
typedef long long ll;
const int maxn=4*1e3+5;
int n,t;
ll a[maxn],b[maxn],c[maxn],d[maxn];
ll ans1[maxn*maxn],ans2[maxn*maxn];
int cnt;
ll num;
int Search (ll x)
{
int l=0,r=cnt-1;
while(l<=r)
{
int mid=(l+r)/2;
if(ans2[mid]==x)
{
int num=0;
ll t1=mid,t2=mid;
while(ans2[t1]==x&&t1>=0) t1--,num++;
while(ans2[t2]==x&&t2<cnt) t2++,num++;
return num-1;
}
else if(ans2[mid]>x) r=mid-1;
else l=mid+1;
}
return 0;
}
int main()
{
scanf("%d",&t);
int q=0;
while(t--)
{
num=0,cnt=0;
scanf("%d",&n);
for (int i=0;i<n;i++)
{
scanf("%lld%lld%lld%lld",&a[i],&b[i],&c[i],&d[i]);
}
if(q) printf("\n");
q++;
for (int i=0;i<n;i++)
{
for (int j=0;j<n;j++)
{
ans1[cnt]=a[i]+b[j];
ans2[cnt]=c[i]+d[j];
cnt++;
}
}
sort(ans1,ans1+cnt);
sort(ans2,ans2+cnt);
for (int i=0;i<cnt;i++)
{
num+=Search(-ans1[i]);
}
printf("%lld\n",num);
}
return 0;
}