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 }

 

posted @ 2019-10-28 21:52  VBL  阅读(129)  评论(0编辑  收藏  举报