题意:n行数,4列,要求每列找1个数,然后4个数之和为0,问有多少种选法。
思路:记录前面两列两两之和,后面两列两两之和,然后将后者排序,然后对于每前两数之和在后面找到和为0的区间即可。
#include<iostream>
#include<cstdio>
#include<cstring>
#include<map>
#include<vector>
#include<algorithm>
#define maxn 1<<28
using namespace std;
int a[5000],b[5000],c[5000],d[5000];
int f[16000005],l[16000005];
int n,fnum,lnum;
int main()
{
while(scanf("%d",&n)!=EOF)
{
fnum=lnum=0;
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++)
{
f[fnum++]=a[i]+b[j];
l[lnum++]=c[i]+d[j];
}
}
sort(l,l+lnum);
int ans=0;
for(int i=0; i<fnum; i++)
{
int fst=-1,last=lnum;
int high=lnum-1,low=0,mid;
while(low<=high)
{
mid=(low+high)/2;
if(l[mid]+f[i]<0)
{
fst=max(fst,mid);
low=mid+1;
}
else high=mid-1;
}
high=lnum-1;
low=0;
while(low<=high)
{
mid=(low+high)/2;
if(l[mid]+f[i]>0)
{
last=min(last,mid);
high=mid-1;
}
else low=mid+1;
}
ans+=last-fst-1;
}
cout<<ans<<endl;
}
return 0;
}