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

题目链接:http://poj.org/problem?id=2785

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).

题目大意,给出n行数,没行数有4个数字,从四列数字中找出一组数字,让他们之和等于0,问有多少种组合;

思路:暴力肯定超时,因此我们可以先将后两项的所有组合处理出来,然后对于每前两项,二分查找有没有符合要求的数字,注意,可能有重复的出现,因此我i们要找他们的边界值,找出重复的个数;复杂度O(n^2logn)

ac:

#include<stdio.h>
#include<string.h>  
#include<math.h>  
  
//#include<map>   
//#include<set>
#include<deque>  
#include<queue>  
#include<stack>  
#include<bitset> 
#include<string>  
#include<iostream>  
#include<algorithm>  
using namespace std;  

#define ll long long  
#define INF 0x3f3f3f3f  
#define mod 1000000007
//#define max(a,b) (a)>(b)?(a):(b)
//#define min(a,b) (a)<(b)?(a):(b) 
#define clean(a,b) memset(a,b,sizeof(a))// 水印 
//std::ios::sync_with_stdio(false);

int n;
ll arr[4100][5];
ll sum2[16000100];

bool cmp(ll a,ll b)
{
	return a<b;
}

int main()
{
	std::ios::sync_with_stdio(false);
	while(cin>>n)
	{
		ll ans=0;
		clean(arr,0);
		clean(sum2,0);
		for(int i=1;i<=n;++i)
		{
			for(int j=1;j<=4;++j)
				cin>>arr[i][j];
		}
		int k=1;
		for(int i=1;i<=n;++i)
		{
			for(int j=1;j<=n;++j)
				sum2[k++]=arr[i][3]+arr[j][4];
		}
		sort(sum2+1,sum2+k,cmp);
//		for(int i=0;i<=k;++i)
//			cout<<sum2[i]<<endl;
		for(int i=1;i<=n;++i)
		{
			for(int j=1;j<=n;++j)
			{
				ll sum1=arr[i][1]+arr[j][2];
				int l=0,r=k,mid;
				while(r-l>1)
				{
					mid=(l+r)>>1;
					if(sum1+sum2[mid]>0)
						r=mid-1;
					else if(sum1+sum2[mid]<0)
						l=mid;
					else//最后符合的向取最左边 (右向左逼近) 
						r=mid;
				}
				//cout<<r<<" "<<l<<" ";
				int ansl=r;
				l=0,r=k;
				while(r-l>1)
				{
					mid=(l+r)>>1;
					if(sum1+sum2[mid]>0)
						r=mid;
					else if(sum1+sum2[mid]<0)
						l=mid+1;
					else//最后符合的向取最右边 (左向右逼近) 
						l=mid;
				}
				//cout<<r<<" "<<l<<" ";
				int ansr=l;
				//cout<<i<<" "<<ansr<<" "<<ansl<<" ";
                 //结果可能是一个范围
				if(ansr>ansl&&(sum1+sum2[ansr]==0&&sum1+sum2[ansl]==0))
					ans=ans+ansr-ansl+1;
				else if(ansr==ansl&&sum1+sum2[ansl]==0)
					ans++;
			}
		}
		cout<<ans<<endl;
	}
}

猜你喜欢

转载自blog.csdn.net/qq_40482358/article/details/81431890
今日推荐