给定一个长度为 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);
- }