《算法竞赛进阶指南》 临值查找

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

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

啥也不会hh

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值