给定一个长度为 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
##其思想在于 我们建立双向链表,将原数组A1…AnA1…An从小到大排序,并增加一个数组B记录An原本的排列
思路
step1:1 5 3 其坐标是1 2 3
step2:进行排序 得到 1 3 5 其坐标 1 3 2 (原始坐标)
step4:我们从坐标最后一位i,即坐标3,开始进行计算min1≤j<i|Ai−Aj| ,因为不会有其它位在最后一位i之后了,
可以保证最后一位i的左右位置即坐标1和坐标2都小于它(坐标3)
(原始坐标) 1 3 2 其中 1<3 ,2<3;
step5 最后坐标3的元素被判断结束,我们可以删除它,即变为1 3
结构:
我们模拟双向链表来实现删除其中的元素。
pair用于存储元素及其原始坐标。
接下来将其排序,再创建一个数组P用来映射,将变换过的排序以顺序读入,
l和r用来记录该数组该位置前一个元素和后一个元素。
通过l和r进行前后遍历,当数组被删除同时改变l和r数组的结构即可,即上一位r指向该节点的下一位,
下一位l指向该节点前一位。
#include <iostream>
#include <algorithm>
#include <cstdio>
#include <vector>
#include <utility>
using namespace std;
const int N = 1e5 + 10;
int p[N], l[N], r[N], n;
pair<int, int> a[N], ans[N];
int main() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
cin >> n;
for (int i = 1; i <= n; i++) {
cin >> a[i].first;
a[i].second = i;
}
a[0].first = 1e9;
a[n + 1].first = -1e9;
sort(a + 1, a + n + 1);
for (int i = 1; i <= n; i++) {
p[a[i].second] = i;
l[i] = i - 1;
r[i] = i + 1;
}
for (int i = n; i >= 2; i--) {
int pos = p[i];
int Left = l[pos];
int Right = r[pos];
int vl = abs(a[pos].first - a[Left].first);
int vr = abs(a[pos].first - a[Right].first);
if (vl <= vr) {
ans[i].first = vl;
ans[i].second = a[Left].second;
}
else {
ans[i].first = vr;
ans[i].second = a[Right].second;
}
r[Left] = Right;
l[Right] = Left;
}
for (int i = 2; i <= n; i++) {
cout << ans[i].first << " " << ans[i].second << "\n";
}
return 0;
}
标签:int,pos,邻值,查找,坐标,数组,include,first
From: https://www.cnblogs.com/AnnaStore/p/18593885