HDU 6087 Rikka with Sequence 可持久化treap (看题解)

HDU 6087 

学习了一手可持久化treap

#include<bits/stdc++.h>
#define LL long long
#define LD long double
#define ull unsigned long long
#define fi first
#define se second
#define mk make_pair
#define PLL pair<LL, LL>
#define PLI pair<LL, int>
#define PII pair<int, int>
#define SZ(x) ((int)x.size())
#define ALL(x) (x).begin(), (x).end()
#define fio ios::sync_with_stdio(false); cin.tie(0);

using namespace std;

const int N = 2e5 + 7;
const int inf = 0x3f3f3f3f;
const LL INF = 0x3f3f3f3f3f3f3f3f;
const int mod = 1e9 + 7;
const double eps = 1e-8;
const double PI = acos(-1);

template<class T, class S> inline void add(T &a, S b) {a += b; if(a >= mod) a -= mod;}
template<class T, class S> inline void sub(T &a, S b) {a -= b; if(a < 0) a += mod;}
template<class T, class S> inline bool chkmax(T &a, S b) {return a < b ? a = b, true : false;}
template<class T, class S> inline bool chkmin(T &a, S b) {return a > b ? a = b, true : false;}

mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());


int n, m, init, root, top, v[N];

struct Treap {
#define l(u) a[u].ch[0]
#define r(u) a[u].ch[1]
    struct Node {
        int ch[2];
        int val, sz;
        LL sum;
    };

    int tot;
    Node a[2750000];

    inline int NewNode(int x) {
        tot++;
        a[tot].ch[0] = a[tot].ch[1] = 0;
        a[tot].val = a[tot].sum = x; a[tot].sz = 1;
        return tot;
    }

    inline int CpyNode(int id) {
        tot++;
        a[tot] = a[id];
        return tot;
    }

    inline void pull(int u) {
        a[u].sz = a[l(u)].sz + a[r(u)].sz + 1;
        a[u].sum = a[l(u)].sum + a[r(u)].sum + a[u].val;
    }

    void Split(int w, int k, int &u, int &v) {
        if(!w) {
            u = v = 0;
            return;
        }
        if(k >= a[l(w)].sz + 1) {
            u = CpyNode(w);
            Split(r(w), k - a[l(w)].sz - 1, r(u), v);
            pull(u);
        } else {
            v = CpyNode(w);
            Split(l(w), k, u, l(v));
            pull(v);
        }
    }

    void Merge(int &w, int u, int v) {
        if(!u || !v) {
            w = u | v;
            return;
        }
        if(rng() % (a[u].sz + a[v].sz) < a[u].sz) {
            w = CpyNode(u);
            Merge(r(w), r(u), v);
        } else {
            w = CpyNode(v);
            Merge(l(w), u, l(v));
        }
        pull(w);
    }

    LL query(int &u, int l, int r) {
        int L, M, R;
        Split(u, r, L, R);
        Split(L, l - 1, L, M);
        LL ret = a[M].sum;
        Merge(L, L, M);
        Merge(u, L, R);
        return ret;
    }

    void update1(int &u, int l, int r, int k) {
        int L1, R1, M1, L2, R2, M2;

        Split(u, l - 1, L1, R1);
        Split(L1, l - k - 1, L1, M1);

        Split(u, r, L2, R2);
        Split(L2, l - 1, L2, M2);

        while(a[M1].sz < r - l + 1) Merge(M1, M1, M1);

        Split(M1, r - l + 1, M1, M2);

        Merge(L2, L2, M1);
        Merge(u, L2, R2);
    }

    void update2(int &u, int v, int l, int r) {
        int L1, M1, R1, L2, M2, R2;

        Split(u, r, L1, R1);
        Split(L1, l - 1, L1, M1);

        Split(v, r, L2, R2);
        Split(L2, l - 1, L2, M2);

        Merge(L1, L1, M2);
        Merge(u, L1, R1);
    }

    void build(int &u, int l, int r) {
        if(l > r) {
            u = 0;
            return;
        }
        int mid = l + r >> 1;
        u = NewNode(v[mid]);
        build(l(u), l, mid - 1);
        build(r(u), mid + 1, r);
        pull(u);
    }

    void dfs(int u) {
        if(!u) return;
        dfs(l(u));
        v[++top] = a[u].val;
        dfs(r(u));
    }

    void ReBuild() {
        tot = a[init].sz;
        top = 0;
        dfs(root);
        build(root, 1, n);
    }
} treap;


int main() {
    scanf("%d%d", &n, &m);
    for(int i = 1; i <= n; i++) {
        scanf("%d", &v[i]);
    }

    treap.build(init, 1, n);
    root = init;

    int op, l, r, k;

    while(m--) {
        scanf("%d%d%d", &op, &l, &r);

        if(op == 1) {
            printf("%lld\n", treap.query(root, l, r));
        } else if(op == 2) {
            scanf("%d", &k);
            treap.update1(root, l, r, k);
        } else {
            treap.update2(root, init, l, r);
        }

        if(treap.tot >= 2500000) {
            treap.ReBuild();
        }
    }
    return 0;
}

/*
*/

猜你喜欢

转载自www.cnblogs.com/CJLHY/p/11110420.html
今日推荐