【数据结构】无旋Treap

维护翻转操作

struct Treap {

private:

    static const int MAXN = 200000 + 10;
    int ls[MAXN], rs[MAXN];
    int rnd[MAXN], siz[MAXN];
    int del[MAXN], dnt;
    int cnt, root;

    int val[MAXN];
    ll sum[MAXN];

    bool rev[MAXN];

    int NewNode(int v) {
        int o = dnt ? del[dnt--] : ++cnt;
        ls[o] = 0, rs[o] = 0;
        rnd[o] = rand(), siz[o] = 1;
        val[o] = v, sum[o] = (ll)v;
        rev[o] = 0;
        return o;
    }

    void PushUp(int o) {
        siz[o] = siz[ls[o]] + siz[rs[o]] + 1;
        sum[o] = sum[ls[o]] + sum[rs[o]] + val[o];
    }

    void PushDown(int o) {
        if(rev[o]) {
            swap(ls[o], rs[o]);
            rev[ls[o]] ^= 1;
            rev[rs[o]] ^= 1;
            rev[o] = 0;
        }
    }

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

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

public:

    void Clear() {
        dnt = 0, cnt = 0;
        root = NewNode(0);
        siz[root] = 0;
    }

    void Insert(int rnk, int v) {
        int L1 = 0, R1 = 0;
        SplitRank(root, rnk - 1, L1, R1);
        L1 = Merge(L1, NewNode(v));
        root = Merge(L1, R1);
    }

    void Erase(int rnk) {
        int L1 = 0, R1 = 0;
        SplitRank(root, rnk - 1, L1, R1);
        int L2 = 0, R2 = 0;
        SplitRank(R1, 1, L2, R2);
        R1 = R2, del[++dnt] = L2;
        root = Merge(L1, R1);
    }

    int Value(int rnk) {
        int L1 = 0, R1 = 0;
        SplitRank(root, rnk - 1, L1, R1);
        int L2 = 0, R2 = 0;
        SplitRank(R1, 1, L2, R2);
        int res = val[L2];
        R1 = Merge(L2, R2);
        root = Merge(L1, R1);
        return res;
    }

    void Reverse(int l, int r) {
        int L1 = 0, R1 = 0;
        SplitRank(root, l - 1, L1, R1);
        int L2 = 0, R2 = 0;
        SplitRank(R1, r - l + 1, L2, R2);
        rev[L2] ^= 1;
        R1 = Merge(L2, R2);
        root = Merge(L1, R1);
    }

} treap;

无旋Treap,常用于维护序列,虽然Splay也可以做。
最大优势:在线,时空复杂度基于元素数量,可以可持久化

与离线离散化的权值线段树相比:在线
与动态开点的权值线段树/01Trie相比:时空复杂度基于元素数量,相对更节省,且写起来简单
与其他平衡树相比:可以可持久化

综上所述,这是一个非常优秀的数据结构,其不可替代性非常强

posted @ 2020-11-26 20:15  purinliang  阅读(141)  评论(0编辑  收藏  举报