1. 程式人生 > 實用技巧 >【資料結構】無旋Treap

【資料結構】無旋Treap

namespace FHQTreap {

    const int MAXN = 200000 + 5;

    int ls[MAXN];
    int rs[MAXN];
    int rd[MAXN];
    int sz[MAXN];
    int ct;
    int rt;

    int va[MAXN];
    ll sm[MAXN];

    void Init() {
        rt = 0;
        ct = 0;
        va[rt] = 0;
        sm[rt] = 0LL;
    }

    void PushUp(int o) {
        sz[o] = sz[ls[o]] + sz[rs[o]] + 1;
        sm[o] = sm[ls[o]] + sm[rs[o]] + va[o];
    }

    void SplitRank(int o, int rk, int &x, int &y) {
        if(!o) {
            x = 0;
            y = 0;
        } else if(rk <= sz[ls[o]]) {
            y = o;
            SplitRank(ls[o], rk, x, ls[o]);
            PushUp(y);
        } else {
            x = o;
            SplitRank(rs[o], rk - sz[ls[o]] - 1, rs[o], y);
            PushUp(x);
        }
    }

    int Merge(int x, int y) {
        if(!x || !y)
            return x | y;
        else if(rd[x] < rd[y]) {
            rs[x] = Merge(rs[x], y);
            PushUp(x);
            return x;
        } else {
            ls[y] = Merge(x, ls[y]);
            PushUp(y);
            return y;
        }
    }

    int NewNode(int v) {
        int o = ++ct;
        ls[o] = 0;
        rs[o] = 0;
        rd[o] = rand();
        sz[o] = 1;
        va[o] = v;
        PushUp(o);
        return o;
    }

    int ValAt(int rk) {
        int o = rt;
        while(o) {
            if(sz[ls[o]] >= rk) {
                o = ls[o];
                continue;
            } else if(sz[ls[o]] + 1 >= rk)
                break;
            else {
                rk -= sz[ls[o]] + 1;
                o = rs[o];
                continue;
            }
        }
        return va[o];
    }

}

using namespace FHQTreap;

這裡提供了ValAt作為二分的典範,事實上平衡樹要維護的東西就是這樣的,不斷在樹上走直到命中某個節點,根據自己的向左走或者向右走的情況,把子樹的資訊統計上來。