UVa 1152 和为0的4个值(二分查找)

https://vjudge.net/problem/UVA-1152

题意:给定4个n元素集合A,B,C,D,要求分别从中选取一个元素a,b,c,d,使得a+b+c+d=0。问有多少种取法。

思路:直接暴力枚举的话是会超时的。可以选把a+b的值枚举出来存储,c和d的值也一样并排序,这样就可以在c和d中进行二分查找了。

 1 #include<iostream>
 2 #include<algorithm>
 3 using namespace std;
 4
 5 const int maxn = 4000 + 5;
 6
 7 int n;
 8 int a[maxn], b[maxn], c[maxn], d[maxn];
 9 int s1[25000000], s2[25000000];
10
11
12 void solve()
13 {
14     int k = 0;
15     int cnt = 0;
16     for (int i = 0; i < n; i++)
17     {
18         for (int j = 0; j < n; j++)
19         {
20             s1[k] = a[i] + b[j];
21             s2[k] = c[i] + d[j];
22             k++;
23         }
24     }
25     sort(s2, s2 + k);
26     for (int i = 0; i < k; i++)
27     {
28         int t = s1[i];
29         int left = 0, right = k-1;
30         while (left <= right)
31         {
32             int mid = (left + right) / 2;
33             if (s2[mid] == -t)
34             {
35                 cnt++;
36                 int p1 = mid;
37                 int p2 = mid;
38                 //因为有可能存在一样的数,所以前后还需要判断
39                 while (s2[++p1] == -t && p1<k )  cnt++;
40                 while (s2[--p2] == -t && p2>=0)  cnt++;
41                 break;
42             }
43             else if (s2[mid]>-t)  right = mid-1;
44             else left = mid+1;
45         }
46     }
47     cout << cnt << endl;
48 }
49
50 int main()
51 {
52     //freopen("D:\\txt.txt", "r", stdin);
53     int t;
54     cin >> t;
55     while (t--)
56     {
57         cin >> n;
58         for (int i = 0; i < n; i++)
59         {
60             cin >> a[i] >> b[i] >> c[i] >> d[i];
61         }
62         solve();
63         if (t)  cout << endl;
64     }
65     return 0;
66 }
时间: 2024-08-25 12:33:15

UVa 1152 和为0的4个值(二分查找)的相关文章

Uva 1152 和为0的4个值 hash/二分

题意: 给定4个n(1 <= n <= 4000)元素集合A, B, C, D,要求分别从中选取一个元素a, b, c, d,使得a+b+c+d = 0,问有多少种选法. 分析: 显然四重循环是过不了的,我先想到的是用map把a+b,c+d分别保存起来,然后在查找统计.超时.... 然后书上说用哈希表去实现,看到有的题解hash表示的太巧妙了,学习一下. 还有就是这题可以用二分解决,先计算出a+b,然后枚举c+d,然后二分找出范围即可. hash 630ms: #include<cstd

(白书训练计划)UVa 1152 4 Values whose Sum is 0(中途相遇法。。)

题目地址:UVa 1152 先枚举A集合与B集合的和,存起来,然后再枚举C集合与D集合的和,看与存起来的值有多少个是互为相反数的.水题.找存起来的值时可以用二分找. 代码如下: #include <iostream> #include <cstdio> #include <string> #include <cstring> #include <stdlib.h> #include <math.h> #include <ctyp

UVA 1152 4 Values Whose Sum is Zero 和为0的4个值

摘要:中途相遇.对比map,快排+二分查找,Hash效率. n是4000的级别,直接O(n^4)肯定超,所以中途相遇法,O(n^2)的时间枚举其中两个的和,O(n^2)的时间枚举其他两个的和的相反数,然后O(logN)的时间查询是否存在. 首先试了下map,果断TLE //TLE #include<cstdio> #include<algorithm> #include<map> using namespace std; const int maxn = 4001; i

uva:10487 - Closest Sums(二分查找)

题目:10487 - Closest Sums 题目大意:给出一组数据,再给出m个查询的数字.要求找到这组数据里的两个数据相加的和最靠近这个查询的数据,输出那两个数据的和. 解题思路:二分查找,这样找到的话,就输出查询的数值,但是要注意找不到的情况:这里最靠近的值不一定是在找不到的时刻的前一次数据,所以要维护最靠近的要查询数的数值. 代码: #include <stdio.h> #include <algorithm> #include <stdlib.h> using

uva 714 - Copying Books(贪心 最大值最小化 二分)

题目描述开头一大堆屁话,我还仔细看了半天..其实就最后2句管用.意思就是给出n本书然后要分成k份,每份总页数的最大值要最小.问你分配方案,如果最小值相同情况下有多种分配方案,输出前面份数小的,就像字典序输出从小到大一样的意思. 这里用到贪心的方法,定义f(x)为真的条件是满足x为最大值使n本书分成k份,那么就是求x的最小值.如何确定这个x就是用的二分法,x一定大于0小于所有值的合,不断的二分再判断是否成立,成立就取左半边,不成立说明太小了就取右半边,写的时候还是没有把二分法理解透彻,我还怕会丢失

uva 1345 Jamie&#39;s Contact Groups (最大流+二分)

uva 1345 Jamie's Contact Groups Description Jamie is a very popular girl and has quite a lot of friends, so she always keeps a very long contact list in her cell phone. The contact list has become so long that it often takes a long time for her to br

js 判断 0&lt;15&lt;30返回值是 true

与java不一样,因为js是弱语言 0<15 返回布尔类型 true,表达式变成true<30, js 有默认类型转换机制,表达式true<30 中的true会 转换成number类型 1,从而变成1< 30,就得到true; 总结:一般不要适应,if(0<15<30)这种,一般用&&  或者 || : js中null,NaN,'',undefined,false,0都为false,js中的对象,数值出了0都为true, var x={o:0,p:1,q

Yougth的最大化(好题,二分查找 0 1分数规划)

Yougth的最大化 时间限制:1000 ms  |  内存限制:65535 KB 难度:4 描述 Yougth现在有n个物品的重量和价值分别是Wi和Vi,你能帮他从中选出k个物品使得单位重量的价值最大吗? 输入 有多组测试数据每组测试数据第一行有两个数n和k,接下来一行有n个数Wi和Vi.(1<=k=n<=10000) (1<=Wi,Vi<=1000000) 输出 输出使得单位价值的最大值.(保留两位小数) 样例输入 3 2 2 2 5 3 2 1 样例输出 0.75 1 #in

UVa 10539 (筛素数、二分查找) Almost Prime Numbers

题意: 求正整数L和U之间有多少个整数x满足形如x=pk 这种形式,其中p为素数,k>1 分析: 首先筛出1e6内的素数,枚举每个素数求出1e12内所有满足条件的数,然后排序. 对于L和U,二分查找出小于U和L的最大数的下标,作差即可得到答案. 1 #include <cstdio> 2 #include <cmath> 3 #include <algorithm> 4 5 typedef long long LL; 6 7 const int maxn = 10