题目链接:https://www.acwing.com/problem/content/description/138/
给定一个长度为 n 的序列 A,A 中的数各不相同。对于 A 中的每一个数 Ai,求:
min1≤j<i|Ai−Aj|min1≤j<i|Ai−Aj|
以及令上式取到最小值的 j(记为 Pi)。若最小值点不唯一,则选择使 Aj较小的那个。
输入格式
第一行输入整数n,代表序列长度。
第二行输入n个整数A1…An,代表序列的具体数值,数值之间用空格隔开。
输出格式
输出共n-1行,每行输出两个整数,数值之间用空格隔开。
分别表示当i取2~n时,对应的min1≤j<i|Ai−Aj|和Pi的值。
数据范围
n≤10^5 |Ai|≤10^9
输入样例:
3
1 5 3
输出样例:
4 1
2 1
题解:动态维护 i 之前与a[i]最接近的数,可能有两个或一个(比a[i]大一点或小一点),我们可以用set维护,利用upper_bound
查找,另外为省去一些讨论,set先插入INT_MAX,INT_MIN,让每次都能查找到。
#pragma GCC optimize(2)
#pragma GCC optimize("inline")
#include<bits/stdc++.h>
using namespace std;
#define ll long long
const int N = 1e5+5;
int a[N];
map<int,int> mp;
set<int> s;
int main() {
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
int n,num;
cin >> n;
s.insert(INT_MAX);
s.insert(INT_MIN);
for(int i=1;i<=n;i++) {
cin >> num;
mp[num] = i;
if(i > 1) {
set<int>::iterator it = s.upper_bound(num);
set<int>::iterator tt = it;
tt--;
int x = abs(*it-num);
int y = abs(*tt-num);
if(x < y) {
cout << x << ' ' << mp[*it] << endl;
}else {
cout << y << ' ' << mp[*tt] << endl;
}
}
s.insert(num);
}
return 0;
}