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

题目传送门


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


题解

  • 第一想法应该就是二分,但是区间断点收缩的判定,就很难确定了。
  • 所以这种方法被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 
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;
	}
}

你可能感兴趣的:(二分)