给定一个长度为 nn 的序列 AA,AA 中的数各不相同。
对于 AA 中的每一个数 AiAi,求:
min1≤j<i|Ai−Aj|min1≤j<i|Ai−Aj|
以及令上式取到最小值的 jj(记为 PiPi)。若最小值点不唯一,则选择使 AjAj 较小的那个。
输入格式
第一行输入整数 nn,代表序列长度。
第二行输入 nn 个整数A1…AnA1…An,代表序列的具体数值,数值之间用空格隔开。
输出格式
输出共 n−1n−1 行,每行输出两个整数,数值之间用空格隔开。
分别表示当 ii 取 2∼n2∼n 时,对应的 min1≤j<i|Ai−Aj|min1≤j<i|Ai−Aj| 和 PiPi 的值。
数据范围
n≤105n≤105,|Ai|≤109|Ai|≤109
输入样例:
3 1 5 3
输出样例:
4 1 2 1
解题思路:
/*
1:将读入的数组从小到大排序,然后将排好队序列记录下标建立成为双向列表
2:然后从第n个数开始枚举,每次计算左右儿子与其的差的最小值,将答案记录在内后,除去该点,继续计算第n - 1个点
*/
代码:
#include <cmath>
#include <cstdio>
#include <iostream>
#include <algorithm>
#define first first
#define y second
using namespace std;
typedef long long LL;
typedef pair<LL, int> PII;
const int N = 100010;
int n;
int l[N], r[N], p[N];
PII a[N], ans[N];
int main()
{
cin >> n;
for (int i = 1; i <= n; i ++ )
{
cin >> a[i].first;
a[i].second = i;//记录他是第几个数
}
sort(a + 1, a + 1 + n);
a[0].first = -4e9, a[n + 1].first = 4e9;//建立哨兵,防止越界
for (int i = 1; i <= n; i ++ )
{
l[i] = i - 1, r[i] = i + 1;
p[a[i].second] = i;//记录排序好后的数组在双向链表中的位置
}
for (int i = n; i >= 2; i -- )//从第n个数往前枚举
{
int point = p[i], left = l[point], right = r[point];
LL left_value = abs(a[left].first - a[point].first);
LL right_value = abs(a[right].first - a[point].first);
//判断谁的绝对值更小,将更小的记录为答案
if (left_value <= right_value) ans[i] = {left_value, a[left].y};
else ans[i] = {right_value, a[right].y};
l[right] = left, r[left] = right;//删掉当前以及枚举过的点
}
for (int i = 2; i <= n; i ++ ) printf("%lld %d\n", ans[i].first, ans[i].y);
}