poj2785 简单二分

4 Values whose Sum is 0

Time Limit: 15000MS   Memory Limit: 228000K
Total Submissions: 19243   Accepted: 5744
Case Time Limit: 5000MS

Description

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 x B x C x D are such that a + b + c + d = 0 . In the following, we assume that all lists have the same size n .

Input

The first line of the input file 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 input file, your program has to write the number quadruplets whose sum is zero.

Sample Input

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

Hint

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

题目大意:四个数列,问你有几种可能的组合满足,a[i]+b[j]+c[k]+d[e]==0;

思路分析:直接遍历所有情况的话,复杂度是n^4。肯定超时,本题应该采用二分做,先进行数组合并,将四个数组合成为两个n*n的数组,然后对

其中一个排序,这样就可以用二分查找另一个数组是否存在对应的数,这样复杂度就变成了n*nlogn^2,这样就不会超时了。

代码:

#include <iostream>
#include <algorithm>
#include <cstdio>
#include <cstring>
#include <queue>
#include <stack>
#define mem(a) memset(a,0,sizeof(a))
using namespace std;
const int inf=0xffffff;
const int maxn=4000+10;
int a[maxn],b[maxn],c[maxn],d[maxn];
int f1[maxn*maxn],f2[maxn*maxn];
int main()
{
    int n;
    while(scanf("%d",&n)!=EOF)
    {
        int cut=0;
        for(int i=0;i<n;i++)
            scanf("%d%d%d%d",&a[i],&b[i],&c[i],&d[i]);
        for(int i=0;i<n;i++)
        {
            for(int j=0;j<n;j++)
            {
                f1[i*n+j]=a[i]+b[j];
                f2[i*n+j]=c[i]+d[j];
            }
        }
        sort(f2,f2+n*n);
    for(int i=0;i<n*n;i++)
    {
        int low=0,high=n*n-1;
    while(low<=high)
    {
        int mid=(low+high)/2;
        if(f2[mid]==-f1[i])
        {
             cut++;
             for(int j=mid-1;j>=0;j--)
             {
                 if(f2[j]!=-f1[i]) break;
                 cut++;
             }
             for(int j=mid+1;j<n*n;j++)
             {
                  if(f2[j]!=-f1[i]) break;
                 cut++;
             }
             break;
        }
      else if(f2[mid]<-f1[i]) low=mid+1;
      else high=mid-1;
    }
    }
    cout<<cut<<endl;
    }
    return 0;
}

时间: 2024-08-02 07:53:15

poj2785 简单二分的相关文章

HDU 2119 Matrix 简单二分匹配

行做x集,列做y集,1就给该行该列连一条边,输出最大匹配边即可 #include<cstdio> #include<cstring> #include<algorithm> #include<iostream> #include<vector> #include<set> using namespace std; #define N 105 int lef[N], pn;//lef[v]表示Y集的点v 当前连接的点 , pn为x点集的

poj 3273 Monthly Expence 简单二分

1 /** 2 大意: 有连续的n天,每一天有一定的花费,将其分成m份,每一份占一天或者连续的几天,求这m份中的最大值 3 思路: 二分其最大上限,看在此最大上线,能分成多少份,若大于m份,说明上限过小,需要扩大上限 4 若小于m份,则说明,下限过大,需要缩小上限. 5 **/ 6 #include <iostream> 7 8 using namespace std; 9 int c[100010]; // 记录,每天的花费 10 int main() 11 { 12 int n,m; 13

poj 2785 4 Values whose Sum is 0 (简单二分)

//每列选一个数相加为0的个数 # include <stdio.h> # include <algorithm> # include <string.h> using namespace std; int ab[4010*4010],cd[4010*4010]; int main() { int n,i,k,j,count,a[4010],b[4010],c[4010],d[4010]; while(~scanf("%d",&n)) { f

hdu-4185.loiol_skimming(简单二分匹配模型)

1 /************************************************************************* 2 > File Name: hdu-4185.oil_skimming.cpp 3 > Author: CruelKing 4 > Mail: [email protected] 5 > Created Time: 2019年09月03日 星期二 09时12分12秒 6 本题思路:简单分析过后就可以知道如果一点a被另一个点b匹配

hdu4190 简单二分

题意是 有n个城市,m个投票箱,接下来n个城市人口数,每个投票箱都不能为空,计算最后投票箱的容量必须达到多少,才能满足需要. 每个城市的人必须只能将票投到自己城市分得得投票箱中.要是容量最小箱子必须得都用上 二分枚举所以的人数 #include<stdio.h> #include<string.h> #include<iostream> using namespace std; int num[500100],n,m; int judge(int x) { int s=

hdu1551 简单二分

题意是给你n跳绳子    分成k段的最大长度          二分枚举长度 #include<stdio.h> #include<string.h> #include<iostream> using namespace std; #define exp 1e-5 double num[11000]; int k,n; int judge(double x) { int s=0; for(int i=1;i<=n;i++) { s+=(int)(num[i]/x)

hdu4004 简单二分+贪心

找到二分的左右值  然后对每一个中值进行判断 #include<stdio.h> #include<string.h> #include<algorithm> #include<iostream> using namespace std; int n,m,L; int num[500010]; int abs(int a) { return a<0?-a:a; } int max(int a,int b) { return a>b?a:b; }

Acwing102 最佳牛围栏 (简单二分)

首先:  (1):   这个*1000的操作肯定是为了防止出现double,这样的话都是整数,好操作!!!!!! (2):  这个首先从暴力方向来想,我们要知道这个的值的话,我们的方法好像只有枚举所有大于等于F的区间来进行操作,但是这样的复杂度是O(N^2-F^2),这个可以等效看作是N^2的,只要数据稍微大一点点,这个算法就会被卡掉 (3): 然后这个可以接受的数据范围是Nlog(N)的? (4): 每块地的平均值最大?   那么这个函数肯定是单调递增的,我们可以二分一个值来验证,看看这个值是

简单二分

1 #include <iostream> 2 3 using namespace std; 4 //upper_bound(a, arr + 10, 7) - a; 5 int search(int *a, int l, int r, int key) 6 { 7 int mid; 8 while(l <= r) 9 { 10 mid = (l + r) / 2; 11 if(a[mid] == key) return mid; 12 if(a[mid] < key) l = m