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

博客围绕HDU 2141题“Can you find it?”展开,介绍题目大意,即输入多组整数,判断是否满足a[i] + b[j] + c[k] = x。解题思路是将等式转化为ai + bj = x - ck,先合并a、b数组,再用二分查找ab数组来求解。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

原题地址: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;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值