UVA1152- 枚举 /二分查找

The SUM problem can be formulated as follows: given four lists A,B,C,D of integer values, compute how many quadruplet (a,b,c,d) ∈ A×B×C×D are such that a+b+c+d = 0. In the following, we assume that all lists have the same size n.

Input
The input begins with a single positive integer on a line by itself indicating the number of the cases following, each of them as described below. This line is followed by a blank line, and there is also a blank line between two consecutive inputs.
The ?rst line of the input ?le contains the size of the lists n (this value can be as large as 4000). We then have n lines containing four integer values (with absolute value as large as 228) that belong respectively to A,B,C and D.

Output
For each test case, your program has to write the number quadruplets whose sum is zero. The outputs of two consecutive cases will be separated by a blank line.

Sample Input
1
6 -45 22 42 -16 -41 -27 56 30 -36 53 -37 77 -36 30 -75 -46 26 -38 -10 62 -32 -54 -6 45
Sample Output
5

Sample Explanation: Indeed, the sum of the ?ve following quadruplets is zero: (-45, -27, 42, 30), (26, 30, -10, -46), (-32, 22, 56, -46), (-32, 30, -75, 77), (-32, -54, 56, 30).

这道题的意思大概是给定四个数组,分别从中取出一个数字,四个数相加为零.

lower_bound( )和upper_bound( )都是利用二分查找的方法在一个排好序的数组中进行查找的。

在从小到大的排序数组中,

lower_bound( begin,end,num):从数组的begin位置到end-1位置二分查找第一个大于或等于num的数字,找到返回该数字的地址,不存在则返回end。通过返回的地址减去起始地址begin,得到找到数字在数组中的下标。

upper_bound( begin,end,num):从数组的begin位置到end-1位置二分查找第一个大于num的数字,找到返回该数字的地址,不存在则返回end。通过返回的地址减去起始地址begin,得到找到数字在数组中的下标。

在从大到小的排序数组中,重载lower_bound()和upper_bound()

lower_bound( begin,end,num,greater<type>() ):从数组的begin位置到end-1位置二分查找第一个小于或等于num的数字,找到返回该数字的地址,不存在则返回end。通过返回的地址减去起始地址begin,得到找到数字在数组中的下标。

upper_bound( begin,end,num,greater<type>() ):从数组的begin位置到end-1位置二分查找第一个小于num的数字,找到返回该数字的地址,不存在则返回end。通过返回的地址减去起始地址begin,得到找到数字在数组中的下标。

参考文章:https://blog.csdn.net/qq_40160605/article/details/80150252

//:(
#include<bits/stdc++.h>
using namespace std;
const int maxn = 4000 + 5;
int n, c, A[maxn], B[maxn], C[maxn], D[maxn], sums[maxn*maxn];

int main() {
    int T;
    scanf("%d", &T);
    while (T--) {
        scanf("%d", &n);
        for (int i = 0; i < n; i++)
            scanf("%d%d%d%d", &A[i], &B[i], &C[i], &D[i]);
        c = 0;
        for (int i = 0; i < n; i++)
        for (int j = 0; j < n; j++)
            sums[c++] = A[i] + B[j];
        sort(sums, sums + c);
        long long cnt = 0;
        for (int i = 0; i < n; i++)
        for (int j = 0; j < n; j++)
            cnt += upper_bound(sums, sums + c, -C[i] - D[j]) - lower_bound(sums, sums + c, -C[i] - D[j]);
        printf("%lld\n", cnt);
        if (T) printf("\n");
    }
    return 0;
}

原文地址:https://www.cnblogs.com/YY666/p/10994942.html

时间: 2024-08-30 15:26:04

UVA1152- 枚举 /二分查找的相关文章

CSU OJ PID=1514: Packs 超大背包问题,折半枚举+二分查找。

1514: Packs Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 61  Solved: 4[Submit][Status][Web Board] Description Give you n packs, each of it has a value v and a weight w. Now you should find some packs, and the total of these value is max, total of

Eqs 折半枚举+二分查找 大水题

Eqs 题目抽象:a1x13+ a2x23+ a3x33+ a4x43+ a5x53=0 (*),给出a1,a2,a3,a4,a5.    ai属于[-50,50]. 求有多少序列   x1,x2,x3,x4,x5 ,xi属于 [-50,50]-{0}. 思路:折半枚举+二分查找 1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 #include <cmath> 5 #inclu

poj3977(折半枚举+二分查找)

题目链接:https://vjudge.net/problem/POJ-3977 题意:给一个大小<=35的集合,找一个非空子集合,使得子集合元素和的绝对值最小,如果有多个这样的集合,找元素个数最少的. 思路:显然,可以用折半搜索,分别枚举一半,最大是2的18次方,复杂度能够满足.因为集合非空,枚举时考虑只在前一半选和只在后一半选的情况.对于前一半后一半都选的情况,把前一半的结果存下来,排序,枚举后一半的时候在前一半里二分查找最合适的即可. 思路不难,实现有很多细节,最开始用dfs写得一直wa,

Subset---poj3977(折半枚举+二分查找)

题目链接:http://poj.org/problem?id=3977 给你n个数,找到一个子集,使得这个子集的和的绝对值是最小的,如果有多种情况,输出子集个数最少的: n<=35,|a[i]|<=10e15 子集个数共有2^n个,所以不能全部枚举,但是可以分为两部分枚举: 枚举一半的所有情况,然后后一半二分即可: #include<iostream> #include<algorithm> #include<string.h> #include<st

poj 1840 Eqs 【解五元方程+分治+枚举打表+二分查找所有key 】

Eqs Time Limit: 5000MS   Memory Limit: 65536K Total Submissions: 13955   Accepted: 6851 Description Consider equations having the following form: a1x13+ a2x23+ a3x33+ a4x43+ a5x53=0 The coefficients are given integers from the interval [-50,50]. It i

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 ma

hdu4430之枚举+二分

Yukari's Birthday Time Limit: 12000/6000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 2549    Accepted Submission(s): 522 Problem Description Today is Yukari's n-th birthday. Ran and Chen hold a celebration party

51nod1010(枚举+二分)

题目链接:https://www.51nod.com/onlineJudge/questionCode.html#!problemId=1010 题意:中文题诶- 思路:求第一个比 x (1<=x<=1e18)大或者等于的数y, 且y的因子只有2, 3, 5,即y=pow(2, i)*pow(3, j)*pow(5, k); 那么显然我们可以通过枚举i, j, k求出所有由2, 3, 5因子构成的数,并将其存入数组中,再二分查找数组中第一个大于等于x的数即为答案: 代码: 1 #include

poj 2452(RMQ+二分查找)

题目链接: http://poj.org/problem?id=2452 题意:在区间[1,n]上找到满足 a[i]<a[k]<a[j] (i<=k<=j) 的最大子区间 (j-i)如不存在输出 -1. 思路:枚举i,找到 i右边第一个不大于(不是小于) a[i]的数a[k](二分查找+RMQ某段区间的最小值是否小于a[i].最后确定到一个点),于是我们可以得到在区间[i,k-1]范围内的数都会大于 a[i] ,所以对于下标i,它对应的最长区间必定在[i,k-1]之间. 所以,我们

(二分最大流) 最大流 + 二分查找 小结

做最大流题目的时候会遇到一种需要用二分查找的题型: (poj2455) 一张无向图中有 N 个点,M 条边,每条边都有一个权值,且每条边只能用一次,要求找出 T 条从 1 到 N 的路径,使这 T 条路径所经过的边中,权值的最大值最小. 转化为最大流模型:T就是最大流,每条边只能用一次在网络流中就是容量为1.然后二分查找(枚举),边权小于或等于mid的边就加一条容量为1的网络流的边.最后知道最大流ans与T相等的最小的mid就是所求. 在二分查找的时候,与一般的二分查找还是有区别的,一般不能有“