【LG5055】可持久化文艺平衡树

【LG5055】可持久化文艺平衡树

题面

洛谷

题解

终于不可以用\(Trie\)水了。。。

和普通的\(FHQ\;treap\)差不多

注意一下\(pushdown\)\(split\)要新开节点

代码

#include <iostream> 
#include <cstdio> 
#include <cstdlib> 
#include <cstring> 
#include <cmath> 
#include <algorithm>
#include <ctime> 
using namespace std; 
inline int gi() {
    register int data = 0, w = 1;
    register char ch = 0;
    while (!isdigit(ch) && ch != '-') ch = getchar(); 
    if (ch == '-') w = -1, ch = getchar();
    while (isdigit(ch)) data = 10 * data + ch - '0', ch = getchar();
    return w * data; 
}
const int MAX_N = 2e5 + 5; 
struct Node {
    int ls, rs, pri, val, size; 
    long long sum; 
    bool rev; 
} t[MAX_N << 6]; 
int rub[MAX_N << 6], cur, rubtop, rt[MAX_N];
inline int newNode(int v = 0) { 
    int o = rubtop ? rub[rubtop--] : ++cur; 
    t[o].val = t[o].sum = v; t[o].pri = rand(); t[o].size = 1; 
    t[o].ls = t[o].rs = t[o].rev = 0; 
    return o; 
}
inline int clone(int y) { 
    int x = rubtop ? rub[rubtop--] : ++cur; 
    t[x] = t[y]; 
    return x; 
} 
inline void pushup(int o) {
    t[o].size = t[t[o].ls].size + t[t[o].rs].size + 1; 
    t[o].sum = t[t[o].ls].sum + t[t[o].rs].sum + t[o].val; 
} 
inline void pushdown(int o) {
    if (!t[o].rev) return ; 
    swap(t[o].ls, t[o].rs); 
    if (t[o].ls) t[o].ls = clone(t[o].ls), t[t[o].ls].rev ^= 1; 
    if (t[o].rs) t[o].rs = clone(t[o].rs), t[t[o].rs].rev ^= 1; 
    t[o].rev = 0; 
} 
void split(int o, int k, int &ls, int &rs) { 
    if (!o) ls = rs = 0; 
    else { 
        pushdown(o); 
        if (k <= t[t[o].ls].size) rs = clone(o), split(t[rs].ls, k, ls, t[rs].ls), pushup(rs); 
        else ls = clone(o), split(t[ls].rs, k - t[t[o].ls].size - 1, t[ls].rs, rs), pushup(ls); 
    } 
} 
int merge(int x, int y) { 
    if (!(x && y)) return x ^ y; 
    if (t[x].pri < t[y].pri) { 
        pushdown(y); 
        t[y].ls = merge(x, t[y].ls); 
        pushup(y); 
        return y; 
    } else {
        pushdown(x); 
        t[x].rs = merge(t[x].rs, y); 
        pushup(x);
        return x; 
    } 
}
void insert(int &o, int k, int v) { 
    int x, y; 
    split(o, k, x, y); 
    o = merge(merge(x, newNode(v)), y); 
} 
void erase(int &o, int pos) { 
    int x, y, z; 
    split(o, pos, x, z); 
    split(x, pos - 1, x, y);
    rub[++rubtop] = y; 
    o = merge(x, z); 
}
void reverse(int &o, int l, int r) { 
    int x, y, z; 
    split(o, r, x, z); 
    split(x, l - 1, x, y);
    t[y].rev ^= 1; 
    o = merge(merge(x, y), z); 
} 
long long query(int &o, int l, int r) { 
    int x, y, z; 
    split(o, r, x, z); 
    split(x, l - 1, x, y); 
    long long res = t[y].sum; 
    o = merge(merge(x, y), z);
    return res; 
}
long long ans = 0;
int N; 
int main () {
    srand(19260817); 
    N = gi(); 
    for (int i = 1; i <= N; i++) {
        int v = gi(), op = gi(); 
        rt[i] = rt[v]; 
        if (op == 1) { int k = gi() ^ ans, val = gi() ^ ans; insert(rt[i], k, val); }
        else if (op == 2) { int k = gi() ^ ans; erase(rt[i], k); } 
        else if (op == 3) { int l = gi() ^ ans, r = gi() ^ ans; reverse(rt[i], l, r); }
        else { int l = gi() ^ ans, r = gi() ^ ans; printf("%lld\n", ans = query(rt[i], l, r)); }
    } 
    return 0; 
} 
posted @ 2018-12-30 15:43  heyujun  阅读(254)  评论(0编辑  收藏  举报