邻值查找

给定一个长度为 0x13 链表 - 图1 的序列 0x13 链表 - 图20x13 链表 - 图3 中的数各不相同。
对于 0x13 链表 - 图4 中的每一个数 0x13 链表 - 图5,求:
0x13 链表 - 图6
以及令上式取到最小值的 0x13 链表 - 图7(记为 0x13 链表 - 图8)。若最小值点不唯一,则选择使 0x13 链表 - 图9 较小的那个。
输入格式
第一行输入整数 0x13 链表 - 图10,代表序列长度。
第二行输入 0x13 链表 - 图11 个整数0x13 链表 - 图12,代表序列的具体数值,数值之间用空格隔开。
输出格式
输出共 0x13 链表 - 图13 行,每行输出两个整数,数值之间用空格隔开。
分别表示当 0x13 链表 - 图140x13 链表 - 图15 时,对应的 0x13 链表 - 图160x13 链表 - 图17 的值。
数据范围
0x13 链表 - 图18,0x13 链表 - 图19
输入样例:

  1. 3
  2. 1 5 3

输出样例:

  1. 4 1
  2. 2 1

该题可以用平衡树(STL set)求解,在这里我们讨论链表的做法。
把序列 A 从小到大排序,然后依次串成一个链表。注意在排序的同时,建立一个数组 B, 其中 0x13 链表 - 图20 表示原始序列中的 0x13 链表 - 图21 处于链表中的哪个位置(一个指针)。
因为链表有序,所以在链表中,指针 0x13 链表 - 图22 指向的节点 prev 和 next 就分别是 0x13 链表 - 图23 的前驱和后继。通过比较二者与 0x13 链表 - 图24 的差,我们就能求出与 0x13 链表 - 图25 最接近的值。
接下来,我们在链表中删除 $Bn$ 指向的节点,该操作复杂度 0x13 链表 - 图26
此时,我们按同样方法考虑 ![](https://cdn.nlark.com/yuque/__latex/3a174e40d31ba3860660c88e71494432.svg#card=math&code=B
%7Bn-1%7D&id=zD6zC) 的 prev 和 next,再删除 0x13 链表 - 图27
以此类推,最终即可求出每个 0x13 链表 - 图28 最接近的值。
该解法的时间复杂度为 0x13 链表 - 图29

  1. #include <bits/stdc++.h>
  2. using namespace std;
  3. const int N = 100010;
  4. int n;
  5. struct rec{
  6. int val, pos;
  7. }a[N];
  8. int b[N], l[N], r[N];
  9. int res[N], p[N];
  10. bool cmp(rec x, rec y){
  11. return x.val < y.val;
  12. }
  13. int main(){
  14. scanf("%d", &n);
  15. for(int i=1;i<=n;i++){
  16. scanf("%d", &a[i].val);
  17. a[i].pos = i;
  18. }
  19. sort(a + 1, a + 1 + n, cmp);
  20. for(int i=1;i<=n;i++) {
  21. b[a[i].pos] = i;
  22. }
  23. for(int i=1;i<=n;i++){
  24. l[i] = i-1; r[i] = i + 1;
  25. }
  26. l[1] = 0, r[n] = 0;
  27. for(int i=n;i>=2;i--){
  28. int pos = b[i];
  29. if(l[pos] && r[pos]) {
  30. int lval = a[l[pos]].val;
  31. int rval = a[r[pos]].val;
  32. if(abs(lval - a[pos].val) <= abs(rval - a[pos].val)){
  33. res[i] = abs(lval - a[pos].val);
  34. p[i] = a[l[pos]].pos;
  35. } else {
  36. res[i] = abs(rval - a[pos].val);
  37. p[i] = a[r[pos]].pos;
  38. }
  39. } else if(l[pos]) {
  40. res[i] = abs(a[l[pos]].val - a[pos].val);
  41. p[i] = a[l[pos]].pos;
  42. } else {
  43. res[i] = abs(a[r[pos]].val - a[pos].val);
  44. p[i] = a[r[pos]].pos;
  45. }
  46. r[l[pos]] = r[pos];
  47. l[r[pos]] = l[pos];
  48. }
  49. for(int i=2;i<=n;i++){
  50. printf("%d %d\n", res[i], p[i]);
  51. }
  52. return 0;
  53. }