1. 程式人生 > 實用技巧 >AcWing 136 鄰值查詢(連結串列)

AcWing 136 鄰值查詢(連結串列)

題目連結

解題思路

  如果將所有數字按從大到小排序,並且從編號最大的數開始找的話,那麼他的左右兩邊的數肯定就是離他最近的數,計算之後把編號最大的數刪掉,那麼編號次大的數相當於之前編號最大的數...所以利用連結串列來做到O(1)刪除,就能在O(nlogn)的時間內解題。

程式碼

const int maxn = 1e5+10;
P a[maxn], ans[maxn];
int p[maxn];
struct NODE {
    int l,r;
} chain[maxn];
int main() {
    int n; scanf("%d",&n);
    for (int i = 1; i<=n; ++i) {
        scanf("%lld",&a[i].first);
        a[i].second = i;
    }
    sort(a+1,a+n+1);
    a[0] = {-3e9,0}, a[n+1] = {3e9,n+1};
    for (int i = 1; i<=n; ++i) {
        chain[i] = {i-1,i+1};
        p[a[i].second] = i;
    }
    for (int i = n; i>1; --i) {
        int pos = p[i], left = chain[pos].l, right = chain[pos].r;
        ll v_l = a[pos].first-a[left].first, v_r = a[right].first-a[pos].first ;
        if (v_l<=v_r) ans[i] = {v_l,a[left].second};
        else ans[i] = {v_r,a[right].second};
        chain[left].r = right, chain[right].l = left;
    }
    for (int i = 2; i<=n; ++i) printf("%d %d\n",ans[i].first, ans[i].second);
    return 0;
}