题目传送门

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