哈尔滨理工大学软件与微电子学院程序设计竞赛——B.Min Value【二分 & 思维】

本文探讨了一种算法策略,用于在整数数组中找到两个元素,其和的绝对值最小。通过排序和二分查找,该方法有效地定位了目标元素,确保了计算效率。文章提供了详细的AC代码实现。

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

题目传送门


在这里插入图片描述


题解

  • 第一想法应该就是二分,但是区间断点收缩的判定,就很难确定了。
  • 所以这种方法被pass了
  • 换种思路,我们优先找的是 ∣ a i + a j ∣ |a_i+a_j| ai+aj 最小,实际上,对于每一个 a i a_i ai ,去找 − a i -a_i ai 的是最优解。
  • 那么按着这个思路就很好想到了。
  • 排序之后,每次去二分查找 − a i -a_i ai 的位置 p p p
  • 但是不一定会存在,所以需要在 p − 1 , p , p + 1 p-1,p,p+1 p1,p,p+1 三个合法的位置找最优解

AC-Code

#include <bits/stdc++.h>
using namespace std;

const int maxn = 1e5 + 7;
struct NODE {
	int val, id;
	NODE(int v = 0, int id = 0) :val(v), id(id) {}
	bool operator < (const NODE& t)const {
		if (val != t.val)	return val < t.val;
		return id < t.id;
	}
};

NODE arr[maxn];
int main() {
	int N;
	while (cin >> N) {
		for (int i = 1; i <= N; ++i) {
			cin >> arr[i].val;
			arr[i].id = i;
		}
		sort(arr + 1, arr + 1 + N);
		int min_num = 0x7fffffff;
		int min_id = 0x7fffffff;
		for (int i = 1; i <= N; ++i) {
			int p = lower_bound(arr + 1, arr + 1 + N, NODE(-arr[i].val, arr[i].id)) - arr;
			if (p != i) {
				if (min_num > abs(arr[i].val + arr[p].val)) {
					min_num = abs(arr[i].val + arr[p].val);
					min_id = arr[i].id + arr[p].id;
				}
				else if (min_num == abs(arr[i].val + arr[p].val))
					min_id = min(min_id, arr[i].id + arr[p].id);
			}
			if (p - 1 >= 1 && p - 1 != i) {
				if (min_num > abs(arr[i].val + arr[p - 1].val)) {
					min_num = abs(arr[i].val + arr[p - 1].val);
					min_id = arr[i].id + arr[p - 1].id;
				}
				else if (min_num == abs(arr[i].val + arr[p - 1].val))
					min_id = min(min_id, arr[i].id + arr[p - 1].id);
			}
			if (p + 1 <= N && p + 1 != i) {
				if (min_num > abs(arr[i].val + arr[p + 1].val)) {
					min_num = abs(arr[i].val + arr[p + 1].val);
					min_id = arr[i].id + arr[p + 1].id;
				}
				else if (min_num == abs(arr[i].val + arr[p + 1].val))
					min_id = min(min_id, arr[i].id + arr[p + 1].id);
			}
		}
		cout << min_num << " " << min_id << endl;
	}
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值