HDU2141/POJ2785(二分查找)

HDU - 2141 Can you find it?

Give you three sequences of numbers A, B, C, then we give you a number X. Now you need to calculate if you can find the three numbers Ai, Bj, Ck, which satisfy the formula Ai+Bj+Ck = X. 
Input

There are many cases. Every data case is described as followed: In the first line there are three integers L, N, M, in the second line there are L integers represent the sequence A, in the third line there are N integers represent the sequences B, in the forth line there are M integers represent the sequence C. In the fifth line there is an integer S represents there are S integers X to be calculated. 1<=L, N, M<=500, 1<=S<=1000. all the integers are 32-integers. 
Output

For each case, firstly you have to print the case number as the form “Case d:”, then for the S queries, you calculate if the formula can be satisfied or not. If satisfied, you print “YES”, otherwise print “NO”. 
Sample Input

3 3 3 
1 2 3 
1 2 3 
1 2 3 



10

Sample Output

Case 1: 
NO 
YES 
NO

问题求A+B+C=X是否存在

暴力求解求出三个数组所有值的可能然后从中查找是否有该值是不可行的,其时间复杂度为O(N^3)。

可以将等式进行变换为A+B=X-C,这样需要在A+B所有的可能值中查找X-C是否存在,将时间复杂度降为O(N^2),同时查找我们使用二分查找更快速。

#include<iostream>
#include<algorithm>
using namespace std;
int a[501], b[501],c[501],box[250005], s;     //box注意开大,避免数组内存不够
int l, n, m, k;
int binary_search(int x)                      //在box中二分查找x
{
	int left = 1, right = k;
	while (left <= right)
	{
		int mid = (left + right) / 2;
		if (x > box[mid])
			left = mid + 1;
		else if (x < box[mid])
			right = mid - 1;
		else
			return 1;
	}
	return 0;
}
int main()
{
	int cases = 0;
	while (scanf("%d%d%d", &l, &n, &m) != EOF)
	{
		cases++;
		for (int i = 1; i <= l; i++)
			cin >> a[i];
		for (int i = 1; i <= l; i++)
			cin >> b[i];
	    k = 0;
		for (int i = 1; i <= l; i++)             //计算两组数和的所有可能并排序
		{
			for (int j = 1; j <= n; j++)
			{
				box[++k] = a[i] + b[j];
			}
		}
		sort(box + 1, box + k+1);
		for (int i = 1; i <= l; i++)
			cin >> c[i];
		cin >> s;
		cout << "Case " << cases << ':' << endl;
		while (s--)
		{
			int x;
			cin >> x;
			int flag = 0;
			for (int i = 1; i <= m; i++)
			{
				if (binary_search(x - c[i]))      
				{
					flag = 1;
					break;
				}
			}
			if (flag)
				cout << "YES" << endl;
			else
				cout << "NO" << endl;
		}
	}
	return 0;
}

POJ2785  4 Values whose Sum is 0

Time Limit: 15000MS   Memory Limit: 228000K
Total Submissions: 29423   Accepted: 8951
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+B=-(C+D),将A+B所有值放入一个数组中然后从数组中二分查找-(C+D)

所求所有可能的总数,故需要计算-(C+D)在数组中是否存在,存在则有几个,就用到了STL中的上下界二分查找。

#include<iostream>
#include<algorithm>
using namespace std;
int a[4001], b[4001], c[4001], d[4001], box1[16000000], box2[16000000];
int n, k1 = 0, k2 = 0, ans = 0;            //box1中存放A+B,box2中存放C+D
int main()
{
	while (scanf("%d", &n) != EOF)
	{
		k1 = 0, k2 = 0, ans = 0;
		for (int i = 1; i <= n; i++)
			scanf("%d%d%d%d", &a[i], &b[i], &c[i], &d[i]);
		for (int i = 1; i <= n; i++)
			for (int j = 1; j <= n; j++)
				box1[++k1] = a[i] + b[j];
		sort(box1 + 1, box1 + k1 + 1);      //在box1中二分查找,从小到大排序
		for (int i = 1; i <= n; i++)
			for (int j = 1; j <= n; j++)
				box2[++k2] = c[i] + d[j];
		for (int i = 1; i <= k2; i++)
		{
			int x1 = lower_bound(box1 + 1, box1 + k1+1, -box2[i]) - box1;//下界的角标序号
            int x2 = upper_bound(box1 + 1, box1 + k1+1, -box2[i]) - box1; //上界的角标序号
			if (x1 != x2)           //序号不相同则至少存在一个
				ans += (x2 - x1);
		}
		cout << ans << endl;
	}
	return 0;
}

猜你喜欢

转载自blog.csdn.net/slience_646898/article/details/82630226