题目链接:4 Values whose Sum is 0
啊啊啊,这一题真是亏了,应该二分交一发的,只怪那回lower_bound和upper_bound写出阴影了,导致这回都不敢交了(要好好学习一下了)。
题目大意:给你n组数,每组给出四个数,从每一列选出一个数,使得四个数的和为0,问有多少种组合方法。
思路:前两组任意组合,记录所有的情况存入sum1数组中,后两组也任意组合,记录所有的情况存入sum2数组中。将两组数都从小到大排列。遍历sum1中的数,用lower_bound和upper_bound在sum2数组中查找 “-sum1[i]”,求一下和即可。
这回我一定要记住了,不要在记混了,还要在学习一下,手写的查找上限和下限。
代码:
#include<stdio.h>
#include<string.h>
#include<algorithm>
using namespace std;
#define mem(a,b) memset(a,b,sizeof(a))
const int maxn=4009;
int a[maxn],b[maxn],c[maxn],d[maxn];
int sum1[maxn*maxn],sum2[maxn*maxn];
int main()
{
int n;
while(~scanf("%d",&n))
{
for(int i=0; i<n; i++)
scanf("%d%d%d%d",&a[i],&b[i],&c[i],&d[i]);
for(int i=0; i<n; i++)//前两个的组合
for(int j=0; j<n; j++)
sum1[i*n+j]=a[i]+b[j];
for(int i=0; i<n; i++)//后两个的组合
for(int j=0; j<n; j++)
sum2[i*n+j]=c[i]+d[j];
sort(sum1,sum1+n*n);
sort(sum2,sum2+n*n);
int ans=0;
int f;
for(int i=0; i<n*n; i++)
{
if(i-1>=0&&sum1[i]==sum1[i-1])//重复的不用再查了
ans+=f;
else
{
int s=lower_bound(sum2,sum2+n*n,-sum1[i])-sum2;//查下限
int e=upper_bound(sum2,sum2+n*n,-sum1[i])-sum2;//查上限
ans+=e-s;
f=e-s;
}
}
printf("%d\n",ans);
}
return 0;
}