码迷,mamicode.com
首页 > 其他好文 > 详细

poj2785(折半枚举)

时间:2019-01-13 16:13:46      阅读:181      评论:0      收藏:0      [点我收藏+]

标签:过程   ios   pac   暴力   返回   div   条件   class   include   

给定A,B,C,D四个集合,每个集合有n个数,一个元组t={a,b,c,d},其中a,b,c,d分别属于ABCD,且a+b+c+d=0

求这样的元组有多少个

1<=n<=4000

|ai,bi,ci,di|<2^28

分析:

暴力枚举n^4显然行不通,n^3也不可

我们可以先n^2计算出a+b的所有值,然后对于每个c+d,寻找-(c+d)=a+b

至于查找过程,把{a+b}进行排序然后二分查找

代码:

 1 #include<cstdio>
 2 #include<iostream>
 3 #include<cstring>
 4 #include<string>
 5 #include<queue>
 6 #include<vector>
 7 #include<set>
 8 #include<map>
 9 #include<cmath>
10 #include<algorithm>
11 
12 #define ll long long 
13 #define mem(a,b) memset(a,b,sizeof(a))
14 
15 using namespace std;
16 const int maxn=4004;
17 int sum[maxn*maxn];
18 int A[maxn],B[maxn],C[maxn],D[maxn];
19 int cnt=0;
20 int main()
21 {
22     //freopen("in.in","r",stdin);
23     int n;
24     cin>>n;
25     for(int i=1;i<=n;i++)
26     {
27         scanf("%d%d%d%d",&A[i],&B[i],&C[i],&D[i]);
28     }
29     for(int i=1;i<=n;i++)
30     {
31         for(int j=1;j<=n;j++)
32         {
33             sum[cnt++]=A[i]+B[j];
34         }
35     }
36     sort(sum,sum+cnt);
37     ll res=0;
38     for(int i=1;i<=n;i++)
39     {
40         for(int j=1;j<=n;j++)
41         {
42             int t=-(C[i]+D[j]);
43             int l=upper_bound(sum,sum+cnt,t)-lower_bound(sum,sum+cnt,t);
44             res+=l;
45         }
46     }
47     printf("%ld\n", res);
48 }

 

注意:对于每一个c+d,可能不止有一个a+b=-(c+d),要把所有满足条件的a+b都举出来,所以是

int l=upper_bound(sum,sum+cnt,t)-lower_bound(sum,sum+cnt,t);
res+=l;

学到了什么:

  lower_bound是返回大于等于待查找元素的第一个值的位置

  upper_bound是返回大于待查找元素的第一个值的位置(之前一直以为二者是相对的,upper_bound返回的是小于等于待查找元素的第一个位置)

  

 

poj2785(折半枚举)

标签:过程   ios   pac   暴力   返回   div   条件   class   include   

原文地址:https://www.cnblogs.com/codeoosacm/p/10262650.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!