2018-7-16 ACM 刷题日记

<Codeforces - 702C>

题意:

    给两个数组,让第一个数组里每个元素,都与第二个数组的每个元素求差再取绝对值,然后找到第一个数组里每一元素对应的这些差值的最小值,再求这些最小值里的最大值。

思路:

    这是在一套二分专题里的一个题,就是一个二分的思路,有两个封装好的二分函数,lower_bound( ) 和 upper_bound( )。这里介绍下 lower_bound( ) 的用法。

比如说有一个数组 p[maxx],角标是从1 ~ n的,那么

int pos = lower_bound(p + 1, p + n + 1, tmp) - p;

上述代码表示,在 p[1] ~ p[n]的范围内,查找第一个大于等于 tmp 的 p 数组的下标。

明确了lower_bound( )的用法,那我就讲下这题思路:

首先传进两个数组 a[ ], b[ ],然后初始化 ans = 0。

接下来初始化 b[0] = -Inf,b[m + 1] = Inf。

初始化b[0]好理解吧,就是如果lower_bound( )得到 b[1],即pos = 1,那么我要的值就是b[1],但是我每次都进行取 b[pos] 和 b[pos - 1] 与 a[i] 差的最小值,所以初始化 b[0] 一个无穷小就行了,而 b[m + 1],之所以要初始化成一个无穷大,就是因为,如果我找遍 1 ~ m 都没找到大于等于 a[i]的值,那我初始化 b[m +1]为无穷大的时候,维护的时候就不会出错,反正就一个编码习惯吧~就使用lower_bound( )的时候,初始化搜索数组 b[ ] 的b[0]负无穷 和 b[m + 1]正无穷即可。

那么我进行这步操作:

int pos = lower_bound(b + 1, b + m + 1, a[i]) - b;

就得到了数组b中第一个大于等于 a[i]的元素位置,由于这两个数组输入都是排好序的,就不用自行sort( )了,这也说明了:

b[pos] 是第一个大于等于 a[i]的位置的值,那就说明 b[pos - 1]是最后一个小于 a[i] 的位置的值。

换言之,b[pos] 和 b[pos - 1] 是离 a[i]最近的两个数,也就是说,取这两者绝对值的最小值,就是当前的 a[i] 与 b[ ] 数组每个元素求差后再取绝对值的最小值,那么再用max维护一下这些最小值里的最大值即可。

本人AC代码:

#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include <iostream>
#include <algorithm>
using namespace std;
typedef long long ll;
const ll Inf = 1e15;
const int maxx = 1e5 + 7;
int n, m;
ll a[maxx], b[maxx];

int main() {
	scanf("%d %d", &n, &m);
	for(int i = 1; i <= n; i++) scanf("%I64d", &a[i]);
	for(int i = 1; i <= m; i++) scanf("%I64d", &b[i]);
	ll ans = 0;
	b[0] = -Inf, b[m + 1] = Inf;
	for(int i = 1; i <= n; i++) {
		int pos = lower_bound(b + 1, b + m + 1, a[i]) - b;
		ll x = abs(a[i] - b[pos]);
		ll y = abs(a[i] - b[pos - 1]);
		ll minx = min(x, y);
		ans = max(ans, minx);
	}
	cout << ans << endl;
}

猜你喜欢

转载自blog.csdn.net/ericgipsy/article/details/81060901