题意:给定4个N元素几个A,B,C,D,要求分别从中选取一个元素a,b,c,d使得a+b+c+d=0。问有多少种选法。(N≤4000,D≤2^28)

解法:首先我们从最直接最暴力的方法开始思考:四重循环O(n^4)枚举;三重循环枚举,把剩下的一个集合排序后二分查找,O(n^3 log n)。在进一步想,运用“中途相遇法”:从两个不同的方向来解决问题,最后“汇集”到一起的方法。(有类似于“双向广度优先搜索”的思想)通过两重循环枚举出A,B两个集合中的元素可组成的和,一般想到开个以和为值的数组记录个数。但是由于D值有2^28这么大,所以不行。于是——解决技巧很厉害!(。ì _ í  。)

实现1:既然不能将相同的数一个个竖向累积在一个数组位,那就可以把这些相同的数横向拉伸,排成一排。使用STL库头文件algorithm里的upper_bound和lower_bound函数直接查找到>d和>=d的数的位置,相减就是d值的数的个数。这样的时间复杂度是O(n^2 log n)。

 1 #include<cstdio>
2 #include<cstdlib>
3 #include<cstring>
4 #include<algorithm>
5 #include<iostream>
6 using namespace std;
7
8 const int N=4010;
9 int a[N],b[N],c[N],d[N],sum[N*N];
10
11 int main()
12 {
13 int T;
14 scanf("%d",&T);
15 while (T--)
16 {
17 int n;
18 scanf("%d",&n);
19 for (int i=1;i<=n;i++)
20 scanf("%d%d%d%d",&a[i],&b[i],&c[i],&d[i]);
21 int m=0;
22 for (int i=1;i<=n;i++)
23 for (int j=1;j<=n;j++)
24 sum[++m]=a[i]+b[j];
25 sort(sum+1,sum+1+m);
26 long long cnt=0;//long long
27 for (int i=1;i<=n;i++)
28 for (int j=1;j<=n;j++)
29 cnt+=upper_bound(sum+1,sum+1+m,-c[i]-d[j])-lower_bound(sum+1,sum+1+m,-c[i]-d[j]);
30 printf("%lld\n",cnt);
31 if (T) printf("\n");
32 }
33 return 0;
34 }

STL库实现

实现2:当然检索的高效算法 Hash也是可以的。我这里用的是闭散列表储存,即%一个大整数(一般是质数)之后放在相应的位置。若该位置已存储了其他数,则将这个数一直往后推直到一个空的位置。由于和的个数最多为n^2,小于列表的长度足够存储,那么就算和的值很大也不影响了。
   关于具体代码我再解释一些:1.常量的0x7fffff表示16进制的7fffff,f是15,即2^23;2.结构体哈希表重载了运算符[],这样就可以直接得到每个数的个数了;3.用&运算而不是%,可能是因为运算速度或存储空间,改成%就RE,但其实它们的意思是一样的,目的都是使数较集中的放在一起。

 1 #include<cstdio>
2 #include<cstdlib>
3 #include<cstring>
4 #include<iostream>
5 using namespace std;
6
7 const int N=4010;
8 int a[N],b[N],c[N],d[N];
9
10 struct ha_map
11 {
12 static const int mod=0x7fffff;
13 int s[mod+1],d[mod+1];
14 void clear() {memset(s,0,sizeof(s));}
15 int& operator [] (int x)
16 {
17 int i;
18 for (i=x&mod;s[i]&&d[i]!=x;i=(i+1)&mod);
19 d[i]=x;
20 return s[i];
21 }
22 }ha;
23
24 int main()
25 {
26 int T;
27 scanf("%d",&T);
28 while (T--)
29 {
30 int n;
31 scanf("%d",&n);
32 for (int i=1;i<=n;i++)
33 scanf("%d%d%d%d",&a[i],&b[i],&c[i],&d[i]);
34 ha.clear();
35 for (int i=1;i<=n;i++)
36 for (int j=1;j<=n;j++)
37 ha[a[i]+b[j]]++;
38 long long cnt=0;//long long
39 for (int i=1;i<=n;i++)
40 for (int j=1;j<=n;j++)
41 cnt+=ha[-c[i]-d[j]];
42 printf("%lld\n",cnt);
43 if (T) printf("\n");
44 }
45 return 0;
46 }

Hash实现

Hash的速度是STL库的4倍多~~ (-ω-*)

【uva 1152】4 Values Whose Sum is Zero(算法效率--中途相遇法+Hash或STL库)的更多相关文章

  1. UVA 1152 4 Values whose Sum is 0 (枚举+中途相遇法)(+Java版)(Java手撕快排+二分)

    4 Values whose Sum is 0 题目链接:https://cn.vjudge.net/problem/UVA-1152 ——每天在线,欢迎留言谈论. 题目大意: 给定4个n(1< ...

  2. uva 1152 4 values whose sum is zero ——yhx

    The SUM problem can be formulated as follows: given four lists A;B;C;D of integer values, computehow ...

  3. UVa 1152 -4 Values whose Sum is 0—[哈希表实现]

    The SUM problem can be formulated as follows: given four lists A, B, C, D of integer values, compute ...

  4. UVA - 1152 4 Values whose Sum is 0(中途相遇法)

    题意:从四个集合各选一个数,使和等于0,问有多少种选法. 分析:求出来所有ai + bi,在里面找所有等于ci + di的个数. #pragma comment(linker, "/STAC ...

  5. UVa 1152 4 Values whose Sum is 0

    题意:给出n,四个集合a,b,c,d每个集合分别有n个数,分别从a,b,c,d中选取一个数相加,问使得a+b+c+d=0的选法有多少种 看的紫书,先试着用hash写了一下, 是用hash[]记录下来a ...

  6. UVA 1152 4 Values Whose Sum is Zero 和为0的4个值 (中途相遇)

    摘要:中途相遇.对比map,快排+二分查找,Hash效率. n是4000的级别,直接O(n^4)肯定超,所以中途相遇法,O(n^2)的时间枚举其中两个的和,O(n^2)的时间枚举其他两个的和的相反数, ...

  7. UVA - 1152 4 Values whose Sum is 0问题分解,二分查找

    题目:点击打开题目链接 思路:暴力循环显然会超时,根据紫书提示,采取问题分解的方法,分成A+B与C+D,然后采取二分查找,复杂度降为O(n2logn) AC代码: #include <bits/ ...

  8. UVA - 1152 --- 4 Values whose Sum is 0(二分)

    问题分析 首先枚举a和b, 把所有a+b记录下来放在一个有序数组,然后枚举c和d, 在有序数组中查一查-c-d共有多少个.注意这里不可以直接用二分算法的那个模板,因为那个模板只能查找是否有某个数,一旦 ...

  9. uva1152 - 4 Values whose Sum is 0(枚举,中途相遇法)

    用中途相遇法的思想来解题.分别枚举两边,和直接暴力枚举四个数组比可以降低时间复杂度. 这里用到一个很实用的技巧: 求长度为n的有序数组a中的数k的个数num? num=upper_bound(a,a+ ...

随机推荐

  1. LeetCode225 用队列实现栈

    使用队列实现栈的下列操作: push(x) -- 元素 x 入栈 pop() -- 移除栈顶元素 top() -- 获取栈顶元素 empty() -- 返回栈是否为空 注意: 你只能使用队列的基本操作 ...

  2. 操作系统-1w字关于内存的总结

    内存的基本概念 什么是内存,有何作用 内存是用于存放数据的硬件.程序执行前需要先放入内存中才能被CPU处理 存储单元 内存中也有一个一个的小房间,每个小房间就是一个存储单元. 如果计算机按照 字节编址 ...

  3. Assuming that agent dropped connection because of access permission

    Assuming that agent dropped connection because of access permission

  4. 【Oracle】Oracle 10g下载路径

    ORACLE 10g下载地址 下载方法: 直接复制下面的链接,打开迅雷,自动会识别下载的内容 Oracle Database 10g Release 2 (10.2.0.1.0) Enterprise ...

  5. kubernets之statefulset资源

    一  了解Statefulset 1.1  对比statefulset与RS以及RC的区别以及相同点 Statefulset是有状态的,而RC以及RS等是没有状态的 Statefulset是有序的,拥 ...

  6. USB过压保护芯片,高输入电压充电器(OVP)

    PW2606B是一种前端过电压和过电流保护装置.它实现了广泛的输入电压范围从2.5VDC到40VDC.过电压阈值可在外部或外部编程设置为内部默认设置.集成功率路径nFET开关的低电阻确保了更好的性能电 ...

  7. scrapy的大文件下载(基于一种形式的管道类实现)

    scrapy的大文件下载(基于一种形式的管道类实现) 爬虫类中将解析到的图片地址存储到item,将item提交给指定的管道 在管道文件中导包:from scrapy.pipelines.images ...

  8. 转 12 jmeter性能测试实战--web程序

    12 jmeter性能测试实战--web程序   项目背景 项目:XX网站环境:Windows需求:并发登录的性能测试场景:1s增加2个线程,运行2000次(线程数20,Ramp-Up seconds ...

  9. CSSmargin击穿问题(子元素margin-top会影响父元素)

    最近写一个H5页面的时候发现了这个被忽视的问题,一时没想到什么原因,搜了半天,记录一下,方便他人踩坑.唉,有些东西不用就忘. 一.问题描述 <div class="container& ...

  10. Spring AOP介绍与使用

    Spring AOP介绍与使用 AOP:Aspect Oriented Programming 面向切面编程 OOP:Object Oriented Programming 面向对象编程 ​ 面向切面 ...