4 Values whose Sum is 0 POJ 2785(折半枚举)
原题
题目分析
依题意,直接对a,b,c,d四个数列进行枚举有n4个状态,考虑折半枚举.分别枚举a,b的组合和c,d的组合,则枚举情况可缩小为2*n2个状态.先把c,d的枚举结果排序,然后在枚举a,b的组合过程中,假设枚举的a,b组合为a[i]+b[j],只需要在c,d的组合中找大小为-(a[i]+b[j])的数量即可,这个找的过程可以用二分来优化,最后复杂度为O(n2log(n2)).
代码
1 #include <cstdio> 2 #include <cstdlib> 3 #include <iostream> 4 #include <algorithm> 5 #include <utility> 6 #include <ctime> 7 #include <cmath> 8 #include <cstring> 9 #include <string> 10 #include <stack> 11 #include <queue> 12 #include <vector> 13 #include <set> 14 #include <map> 15 16 using namespace std; 17 typedef unsigned long long ULL; 18 typedef long long LL; 19 typedef long double LB; 20 const int INF_INT=0x3f3f3f3f; 21 const LL INF_LL=0x3f3f3f3f3f3f3f3f; 22 23 int a[4000],b[4000],c[4000],d[4000]; 24 int cd[16000000]; 25 26 int main() 27 { 28 // freopen("testdata.in","r",stdin); 29 // freopen("std.out","w",stdout); 30 int N; 31 while(cin>>N) 32 { 33 for(int i=0;i<N;i++) 34 scanf("%d %d %d %d",&a[i],&b[i],&c[i],&d[i]); 35 36 for(int i=0;i<N;i++) 37 for(int j=0;j<N;j++) 38 cd[i*N+j]=c[i]+d[j]; 39 sort(cd,cd+N*N); 40 LL ans=0; 41 for(int i=0;i<N;i++) 42 for(int j=0;j<N;j++) 43 { 44 int t=-(a[i]+b[j]); 45 ans+=upper_bound(cd,cd+N*N,t)-lower_bound(cd,cd+N*N,t); 46 } 47 cout<<ans<<endl; 48 } 49 return 0; 50 }