set及链表解决邻值查找

题目简述:

​ 对于序列A中的任意数 A i A_i Ai, 求 m i n 1 ≤ j < i ∣ A i − A j ∣ min_{1\leq j < i}|A_i - A_j| min1j<iAiAj ,即求当前标号之前,与 A i A_i Ai最接近的值及其索引。

方法一:

​ 利用值及索引建立 vector, 然后根据值对原数组进行排序。则可得知对于 A i A_i Ai 数值最接近的为 A i − 1   A i + 1 A_{i-1}\ A_{i+1} Ai1 Ai+1 ,然后根据原数组索引 n 开始倒序循环,这样就可以保证前后两个数一定是索引小于当前索引。

#include <bits/stdc++.h>
using namespace std;

const int N = 1e5 + 5;
const int INF = 2e9 + 7;

struct Node{
    int pos, val;
    Node *pre, *next;
};

Node *head, *tail, *point;

int n;

Node *pos[N];

vector<pair<int, int>> a;

void insert(Node *&p, pair<int,int> &pa) // pay attention to can not use references
{
    // cout << pa.first << " " << pa.second << endl;
    Node *nod = new Node;
    nod -> val = pa.first;
    nod -> pos = pa.second;
    nod -> pre = p;
    nod -> next = p -> next;

    p -> next -> pre = nod;
    p -> next = nod;
    pos[pa.second] = nod;
}

void Initialization()
{
    head = new Node;
    tail = new Node;
    head -> next = tail;
    tail -> pre = head;

    head -> val = INF;
    for (auto &it : a) {
        Node *p = tail -> pre;
        insert(tail -> pre, it);
    }
    tail -> val = -INF;
}

void Del(Node *& p)
{
    Node *pre = p -> pre, *next = p -> next;
    pre -> next = next;
    next -> pre = pre;
    delete p;
}

int main()
{
    int x; cin >> n;
    for (int i = 1; i <= n; i ++) {
        cin >> x;
        a.push_back(make_pair(x, i));
    }

    sort(a.begin(), a.end());

    Initialization();

    /* Node *lis = head;
    while (lis != tail) {
        cout << lis -> val << " ";
        lis = lis -> next;
    } */

    vector<int> ans;
    for (int i = n; i > 1; i --) {
        int x = pos[i]->pre->val, y = pos[i]->val, z = pos[i]->next->val;
        if (y - x <= z - y) ans.push_back(pos[i]->pre->pos);
        else ans.push_back(pos[i]->next->pos);

        Del(pos[i]);
    }

    reverse(ans.begin(), ans.end());

    for(auto &it : ans) cout << it << " " << a[it - 1].first << endl;
    return 0;
}
方法二:

建立set集合, 键值为 p a i r < i n t ,   i n t > pair<int,\ int> pair<int, int>, 可知 set 内部重载了pair的的排序函数, 第一优先级为pair.first, 次优先级为pair.second 。 首先处理边界, 将ser中加入INF -INF,方便处理, 从索引 2 开始循环,每次从set中查询优先级大于 m a k e p a i r ( x , i ) make_pair(x, i) makepair(x,i)的节点及优先级小于其的节点, 选择最接近的节点并记录答案, 最后将当前节点插入set 中。

#include <bits/stdc++.h>
using namespace std;

const int INF = 2e9 + 7;

int main()
{
    int n, x; cin >> n >> x; 
    
    set<pair<int, int>> se;
    se.insert({INF, 0});
    se.insert({-INF, 0});
    se.insert({x, 1});

    vector<pair<int, int>> ans;
    for (int i = 2; i <= n; i ++) {
        cin >> x;
        set<pair<int, int>>::iterator itA = se.upper_bound({x, i});
        auto itB = itA;
        itB --;

        if (x - (*itB).first <= (*itA).first - x) ans.push_back({x - (*itB).first, (*itB).second});
        else ans.push_back({(*itA).first - x, (*itA).second});

        se.insert({x, i});
    }

     for (auto &it : ans) cout << it.first << " " << it.second << endl;
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值