UVA - 10487 - Closest Sums (二分求解)

传送:UVA - 10487

10487 Closest Sums

Given is a set of integers and then a sequence of queries. A query gives you a number and asks to find

a sum of two distinct numbers from the set, which is closest to the query number.

Input

Input contains multiple cases.

Each case starts with an integer n (1 < n ≤ 1000), which indicates, how many numbers are in the

set of integer. Next n lines contain n numbers. Of course there is only one number in a single line. The

next line contains a positive integer m giving the number of queries, 0 < m < 25. The next m lines

contain an integer of the query, one per line.

Input is terminated by a case whose n = 0. Surely, this case needs no processing.

Output

Output should be organized as in the sample below. For each query output one line giving the query

value and the closest sum in the format as in the sample. Inputs will be such that no ties will occur.

Sample Input

5

3

12

17

33

34

3

1

51

30

3

1

2

3

3

1

2

3

3

1

2

3

3

4

5

6

0

Sample Output

Case 1:

Closest sum to 1 is 15.

Closest sum to 51 is 51.

Closest sum to 30 is 29.

Case 2:

Closest sum to 1 is 3.

Closest sum to 2 is 3.

Closest sum to 3 is 3.

Case 3:

Closest sum to 4 is 4.

Closest sum to 5 is 5.

Closest sum to 6 is 5.

思路:首先先输入一堆数,然后排个序,再算出所有的不同的两个数的和,存入另一个数组(用set判重),对该数组排序,然后二分查找结果,注意这里数组要开大点,因为最大1000 *(1000 + 1)/ 2有500500,这里RE了一次

AC代码:

#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <set>
#define LL long long
#define INF 0x3fffffff
using namespace std;

int n, m;
int a[501000];
int sum;

int main() {
	int cas = 1;
	while(scanf("%d", &n), n) {
		int tmp[1005];
		for(int i = 0; i < n; i++) {
			scanf("%d", &tmp[i]);
		}
		sort(tmp, tmp + n);
		sum = 0;
		set<int> se;
		for(int i = 0; i < n - 1; i++) {
			for(int j = i + 1; j < n; j++) {
				int t = tmp[i] + tmp[j];
				if(!se.count(t)) {
					se.insert(t);
					a[sum++] = t;
				}
			}
		}
		sort(a, a + sum);
		//for(int i = 0; i < sum; i++) printf("%d\n", a[i]);

		printf("Case %d:\n", cas ++);
		scanf("%d", &m);
		while(m--) {
			int tt;
			scanf("%d", &tt);
			if(tt >= a[sum - 1]) {
				printf("Closest sum to %d is %d.\n", tt, a[sum - 1]);
			}
			else if(tt <= a[0]) {
				printf("Closest sum to %d is %d.\n", tt, a[0]);
			}
			else {
				int fir = 0, fin = sum - 1;
				while(fir < fin) {
					int m = fir + (fin - fir) / 2;
					if(a[m] < tt) fir = m + 1;
					else fin = m;
				}
				int ans;
				if(abs(a[fin] - tt) > abs(a[fin - 1] - tt)) ans = a[fin - 1];
				else ans = a[fin];
				printf("Closest sum to %d is %d.\n", tt, ans);
			}
		}
	}
	return 0;
}
时间: 2024-10-04 13:10:11

UVA - 10487 - Closest Sums (二分求解)的相关文章

UVA 10487 Closest Sums(二分)

UVA 10487 Closest Sums Given is a set of integers and then a sequence of queries. A query gives you a number and asks to find a sum of two distinct numbers from the set, which is closest to the query number. Input Input contains multiple cases. Each

uva 10487 Closest Sums (遍历&amp;二分查找&amp;&amp;双向查找)

题目大意:先给定n个数字,现在要求算出这n个数字的两两之和保存到sum数组,然后在给定m个数,要求找到和每一个数最接近的sum[i]: 挨个计算每个属于其他数之间的sum,然后排序: 查找时有两种方法:二分查找&&双向查找:当然二分查找的效率比后者高了很多,但是都能AC. 提供一条新思路,并不一定非要用二分. 双向查找: #include<stdio.h> #include<algorithm> #include<stdlib.h> using name

uva:10487 - Closest Sums(二分查找)

题目:10487 - Closest Sums 题目大意:给出一组数据,再给出m个查询的数字.要求找到这组数据里的两个数据相加的和最靠近这个查询的数据,输出那两个数据的和. 解题思路:二分查找,这样找到的话,就输出查询的数值,但是要注意找不到的情况:这里最靠近的值不一定是在找不到的时刻的前一次数据,所以要维护最靠近的要查询数的数值. 代码: #include <stdio.h> #include <algorithm> #include <stdlib.h> using

UVA Closest Sums(二分查找)

Problem D Closest Sums Input: standard input Output: standard output Time Limit: 3 seconds Given is a set of integers and then a sequence of queries. A query gives you a number and asks to find a sum of two distinct numbers from the set, which is clo

UVA10487 Closest Sums【暴力+二分】

Given is a set of integers and then a sequence of queries. A query gives you a number and asks to find a sum of two distinct numbers from the set, which is closest to the query number. Input Input contains multiple cases. ????Each case starts with an

uva-10487 - Closest Sums

暴力枚举后去重最后二分加推断找答案 #include<iostream> #include<map> #include<string> #include<cstring> #include<cstdio> #include<cstdlib> #include<cmath> #include<queue> #include<vector> #include<algorithm> using

UVA.11997- K Smallest Sums, OJ4TH.368 - Magry&#39;s Sum I

感谢算法助教们给了这么一个好题... 题意: 给出n个数组,每个数组有n个元素,我们从每个数组中挑选一个元素,共计n个元素求和,得到共计 $ k^k $ 种sum,求sum中的最小n个值. 利用二分查找符合条件的最大sum值,dfs搜索判断二分条件.最坏时间复杂度 $O(n^{2}log(n*Max(a[i][j])) $ 刘汝佳训练指南上给出了优先队列多路归并的思想. 思路1代码: 1 #include<cstdio> 2 #include<iostream> 3 #includ

hdu3586 树形dp+二分求解

http://acm.hdu.edu.cn/showproblem.php?pid=3586 Problem Description In the battlefield , an effective way to defeat enemies is to break their communication system. The information department told you that there are n enemy soldiers and their network w

uva 1356 - Bridge(积分+二分)

题目链接:uva 1356 - Bridge 题目大意:在一座长度为B的桥上建若干个塔,塔的间距不能超过D,塔的高度为H,塔之间的绳索形成全等的抛物线.绳索的总长度为L.问在建最少塔的情况下,绳索的最下段离地面的高度. 解题思路:贪心的思想求出最少情况下建立的塔数. 二分高度,然后用积分求出两塔之间绳索的长度. C++ 积分 #include <cstdio> #include <cstring> #include <cmath> #include <algori