題目鏈接: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;
}