邻值查找(0x13 链表与邻接表)

简介: 笔记

邻值查找


题意

给定一个长度为 n的序列 A ,A 中的数各不相同。


对于 A 中的每一个数 A i ,求:


m i n 1 ≤ j < i ∣ A i − A j ∣


以及令上式取到最小值的 j (记为 P i )。若最小值点不唯一,则选择使 A j 较小的那个。


思路

将原数组按照权值递增排序后,构造成一个链表,然后按照输入顺序从后往前计算结果,每算出一个数 A i 的结果后,就将其从链表中删除,这样可以保证计算第 i 个数时,所有还存在的数在输入中一定在其前面 满足了题目要求的 1<=j<i


实现细节请看代码注释


代码

#include<bits/stdc++.h>
#define int long long
#define INF 0x3f3f3f3f
#define mod 1000000007
#define MOD 998244353
#define rep(i, st, ed) for (int (i) = (st); (i) <= (ed);++(i))
#define pre(i, ed, st) for (int (i) = (ed); (i) >= (st);--(i))
using namespace std;
typedef long long LL;
typedef pair<int, int> PII;
template<typename T> inline T gcd(T a, T b) { return b ? gcd(b, a % b) : a; }
template<typename T> inline T lowbit(T x) { return x & -x; }
const int N = 1e5 + 10;
int n;
PII a[N]; // 记录每个数的权值和输入的下标
PII res[N]; // 记录答案
int p[N]; // 记录每个数排序后的下标
int l[N], r[N]; // 前向指针和后向指针数组
void solve() {
  cin >> n;
  rep(i, 1, n) {
    cin >> a[i].first; // 读入权值
    a[i].second = i; // 记录下标
  }
  sort(a + 1, a + 1 + n); // 按权值递增排序
  rep(i, 1, n) {
    l[i] = i - 1; // 对排序后的数据构造链表
    r[i] = i + 1;
    p[a[i].second] = i; // 记录排序前的下标对应的排序后的下标
  }
  a[0].first = a[n + 1].first = LLONG_MAX; // 边界
  for (int i = n; i > 1; --i) { // 按输入顺序从后往前计算答案
    int j = p[i]; // j 表示第 i 个输入的数排序后在链表中的位置(下标)
    int left = l[j], right = r[j]; // 当前数在链表中的前驱节点和后继节点的下标
    int v = a[j].first; // 当前节点的权值
    int lv = abs(a[left].first - v); // 与左边节点的差的绝对值
    int rv = abs(a[right].first - v); // 与右边节点的差的绝对值
    if (lv <= rv) { // 如果当前数与 左边的数的差值 小于 与右边的数的插值 按照题目要求选择左边的数
      res[i] = { lv,a[left].second };
      // a[left].second 表示左边的数在原数组中的下标
    }
    else { // 否则选择右边的点
      res[i] = { rv,a[right].second };
    }
    // 将当前节点从链表中删除
    l[right] = left;
    r[left] = right;
  }
  // 按输入顺序输出答案
  rep(i, 2, n) {
    printf("%lld %lld\n", res[i].first, res[i].second);
  }
}
signed main() {
  // int t; cin >> t;
  // while (t--)
    solve();
  return 0;
}


目录
相关文章
|
Java 数据安全/隐私保护
SpringBoot - 优雅的实现【参数分组校验】高级进阶
SpringBoot - 优雅的实现【参数分组校验】高级进阶
730 0
|
7月前
|
JSON 监控 前端开发
如何高效接入日本股市实时数据?StockTV API 对接实战指南
本文详解如何通过StockTV金融API(countryId=35)高效接入日本股市实时行情,涵盖全量股票列表、单股查询、多周期K线、涨跌榜等核心接口,并对比HTTP轮询与毫秒级WebSocket推送方案,助力量化开发与实时应用构建。(239字)
|
存储 前端开发 JavaScript
链动模式融合排队免单:扩散用户裂变网络、提高复购
将链动2+1与排队免单结合的模式及链动3+1模式转化为可运行代码涉及多个技术领域,包括后端开发、前端开发、数据库设计等。本文提供了一个简化的技术框架,涵盖用户管理、订单处理、奖励计算、团队结构等核心功能,并提供了示例代码。同时,强调了安全性、测试与部署的重要性,以确保系统的稳定性和合规性。
R语言如何解决线性混合模型中畸形拟合(Singular fit)的问题
R语言如何解决线性混合模型中畸形拟合(Singular fit)的问题
|
机器学习/深度学习 文字识别 自然语言处理
OCR文字识别技术总结(三)
文本检测任务是找出图像或视频中的文字位置。不同于目标检测任务,目标检测不仅要解决定位问题,还要解决目标分类问题。
1228 0
OCR文字识别技术总结(三)
|
SQL Oracle 关系型数据库
DDL的原理:一篇文章让你豁然开朗
DDL的原理:一篇文章让你豁然开朗
365 0
|
移动开发 Python
Python正则表达式(持续更新,各种字符串筛选,总有一款适合您当前的功能)(1)
Python正则表达式(持续更新,各种字符串筛选,总有一款适合您当前的功能)(1)
556 0
Python正则表达式(持续更新,各种字符串筛选,总有一款适合您当前的功能)(1)
|
Windows 数据库 数据安全/隐私保护
|
移动开发 人工智能 算法
什么是快速排序(转)
什么是快速排序 快速排序简介 快速排序(英文名:Quicksort,有时候也叫做划分交换排序)是一个高效的排序算法,由Tony Hoare在1959年发明(1961年公布)。当情况良好时,它可以比主要竞争对手的归并排序和堆排序快上大约两三倍。
1403 0