hdu2141-Can you find it?(二分查找加速搜索)

原题地址:http://acm.hdu.edu.cn/showproblem.php?pid=2141

 题目原文:

Can you find it?

Time Limit: 10000/3000 MS (Java/Others)    Memory Limit: 32768/10000 K (Java/Others)
Total Submission(s): 45692    Accepted Submission(s): 11064


 

Problem Description

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
3
1
4
10

 

 

Sample Output

 

Case 1:
NO
YES
NO

题目大意:

        第一行输入L,N,M , 接下来各行分别输入L, N, M个整数组成a[i], b[j], c[k], 紧接着输入一个整数S,下面再输入S行整数x,要求a[i] + b[j] + c[k] = x. 如果能够等式成立,输出YES,不成立输出NO.

解题思路:

        根据题目数值范围分析,都在int32内。将等式 ai + bj + ck = x 转化成 ai + bj = x - ck; 因为a、b数组范围在500内,不算大,可以先用O(500^2)复杂度将a、b数组合并成一个数组ab,紧接着遍历c数组利用二分查找ab数组使得ab[?]==x-c.

AC代码:

#include <cstdio>
#include <algorithm>
#include <functional>
using namespace std;

const int N = 501;
const int M = 1001;
const int L = N * N;
const char *NO = "NO";
const char *YES = "YES";

int g_la, g_lb, g_lc; // [1, 500]
int g_ls; // [1, 1000]
int g_lab; // [1, 250000]
int g_a[N];
int g_b[N];
int g_c[N];
int g_x[M];
int g_ab[L];

// a + b + c = x ---> a + b = x - c, 合并ab后,ab = x - c
void mergeAB()
{
	int i, j;
	for (g_lab = 0, i = 0; i < g_la; i++)
	{
		for (j = 0; j < g_lb; j++)
		{
			g_ab[g_lab++] = g_a[i] + g_b[j];
		}
	}
	sort(g_ab, g_ab + g_lab, less<int>());
}

// 二分查找ab, 返回大于等于x-c的第一个下标, 如果不等于就返回(负数 - 1)
int bsearch(int arr[], int len, int val)
{
	// 保证arr已经升序排序
	int left = 0;
	int right = len - 1;
	int middle;
	while (left <= right)
	{
		middle = (left + right) >> 1;
		if (arr[middle] < val) left = middle + 1;
		else right = middle - 1;
	}
	// return left;
	if (arr[left] == val) return left;
	else return -left - 1;
}

int main()
{
	int I = 1;
	while (scanf("%d%d%d", &g_la, &g_lb, &g_lc) != EOF)
	{
		int i, j;
		for (i = 0; i < g_la; i++) scanf("%d", &g_a[i]);
		for (i = 0; i < g_lb; i++) scanf("%d", &g_b[i]);
		for (i = 0; i < g_lc; i++) scanf("%d", &g_c[i]);
		scanf("%d", &g_ls);
		for (i = 0; i < g_ls; i++) scanf("%d", &g_x[i]);
		printf("Case %d:\n", I++);
		mergeAB();
		for (i = 0; i < g_ls; i++)
		{
			for (j = 0; j < g_lc; j++) 
			{
				if (bsearch(g_ab, g_lab, g_x[i] - g_c[j]) >= 0)
				{
					printf("%s\n", YES);
					break;
				}
			}
			if (j >= g_lc) printf("%s\n", NO);
		}
	}
	return 0;
}

猜你喜欢

转载自blog.csdn.net/weixin_41645983/article/details/88694799