题目的本质是,在$1$到$i-1$中,找到最接近$a[i]$的数。涉及到查找了,显然可以使用二分。但二分查找应用在有序数组中,难道我们单独维护一个序列,每次加进来一个数,就对它进行一次排序?这显然是不合适的。于是,便想到了可以使用$map$来存储,因为$map$本身是有序的,而且$map$可以记录数的下标,同时提供了$lower_bound$函数。至此,问题解决。
const int N = 1e5 + 5;
int n, a[N];
inline void slove() {
cin >> n;
for (int i = 1; i <= n; i++) {
cin >> a[i];
}
map<int, int> s;
s[a[1]] = 1; // 插入第一个数
for (int i = 2; i <= n; i++) {
auto pos = s.lower_bound(a[i]); // 查找第一个>=a[i]的数
if (pos == s.end()) { // a[i]比所有的数都要大,最大的数是答案
cout << abs(a[i] - (*prev(pos)).first) << " " << (*prev(pos)).second << endl;
}
else if (pos == s.begin()) { // a[i]比所有的数都要小,最小的数是答案
cout << abs(a[i] - (*s.begin()).first) << " " <<(*s.begin()).second << endl;
}
else {
// 因为pos的位置是>=a[i]的,当*pos>a[i]时,我们需要比较一下a[i]是离前面近,还是离后面近
int fst = (*(prev(pos))).first, lst = (*pos).first;
if (a[i] - fst <= lst - a[i]) {
cout << a[i] - fst << " " << (*(prev(pos))).second << endl;
}
else {
cout << lst - a[i] << " " << (*pos).second << endl;
}
}
s[a[i]] = i;
}
}