P5055 【模板】可持久化文艺平衡树 题解

Description

Luogu传送门

Solution

顾名思义,我们要实现的就是可持久化文艺平衡树,也就是带修的文艺平衡树。

前置知识:文艺平衡树,可持久化平衡树

对于每次修改,我们要新建出被修改的那棵子树,所有的修改及查询操作全都是在要求的版本中进行。

修改之后建出新的版本。

我写的时候直接令 \(rt_i = rt_u\)\(u\) 是输入的要求在 \(rt_u\) 上面进行操作),然后把 \(rt_i\) 传到函数里即可。

思路大概就是这样吧。

我用 \(fhq-treap\) 实现的。

注意:插入的 split 时,要 split(pos) 而不是 split(val)!!!我因为这个卡了一晚上!!!!(可能是我太傻了)

Code

splitpushdown 的过程中要新建节点,各种操作中传入 root 的地址便可以像普通的 \(fhq-treap\) 一样写啦,具体见下面代码)

#include <bits/stdc++.h>
#define ll long long
#define ls(x) t[x].l
#define rs(x) t[x].r

using namespace std;

namespace IO{
    inline int read(){
        int x = 0, f = 1;
        char ch = getchar();
        while(!isdigit(ch)) {if(ch == '-') f = -1; ch = getchar();}
        while(isdigit(ch)) x = (x << 3) + (x << 1) + ch - '0', ch = getchar();
        return x * f;
    }

    template <typename T> inline void write(T x){
        if(x < 0) putchar('-'), x = -x;
        if(x > 9) write(x / 10);
        putchar(x % 10 + '0');
    }
}
using namespace IO;

const int N = 2e5 + 10;
int n;
ll lst;
struct fhq_treap{
    int val, siz, wei, l, r;
    ll sum;
    bool rev;
}t[N << 6];
int rt[N], tot;

inline int clone(int y){
    int x = ++tot;
    return t[x] = t[y], tot;
}

inline void pushup(int x){
    t[x].siz = t[ls(x)].siz + t[rs(x)].siz + 1;
    t[x].sum = t[ls(x)].sum + t[rs(x)].sum + t[x].val;
}

inline void pushdown(int x){
    if(t[x].rev){
        swap(ls(x), rs(x));
        if(ls(x)) t[x].l = clone(t[x].l), t[t[x].l].rev ^= 1;
        if(rs(x)) t[x].r = clone(t[x].r), t[t[x].r].rev ^= 1;
        t[x].rev = 0;
    }
}

inline void split(int x, int k, int &a, int &b){
    if(!x) return a = b = 0, void();
    pushdown(x);
    if(k >= t[ls(x)].siz + 1){
        a = clone(x);
        split(rs(x), k - t[ls(x)].siz - 1, rs(a), b);
        pushup(a);
    }
    else{
        b = clone(x);
        split(ls(x), k, a, ls(b));
        pushup(b);
    }
}

inline int merge(int x, int y){
    if(!x || !y) return x | y;
    if(t[x].wei <= t[y].wei){
        pushdown(x);
        rs(x) = merge(rs(x), y);
        return pushup(x), x;
    }else{
        pushdown(y);
        ls(y) = merge(x, ls(y));
        return pushup(y), y;
    }
}

inline int newnode(int k){
    t[++tot].val = k, t[tot].sum = k, t[tot].siz = 1, t[tot].wei = rand();
    return tot;
}

inline void insert(int &root, int p, int k){
    int a, b;
    split(root, p, a, b);
    root = merge(merge(a, newnode(k)), b);
}

inline void remove(int &root, int k){
    int a, b, c;
    split(root, k, a, b);
    split(a, k - 1, a, c);
    root = merge(a, b);
}

inline void reverse(int &root, int l, int r){
    int a, b, c;
    split(root, r, a, c);
    split(a, l - 1, a, b);
    t[b].rev ^= 1;
    root = merge(merge(a, b), c);
}

inline ll query(int &root, int l, int r){
    int a, b, c;
    split(root, r, a, c);
    split(a, l - 1, a, b);
    ll res = t[b].sum;
    root = merge(merge(a, b), c);
    return res;
}

int main(){
    n = read();
    for(int i = 1; i <= n; ++i){
        int u = read(), op = read();
        rt[i] = rt[u];
        if(op == 1){
            int p = read() ^ lst, x = read() ^ lst;
            insert(rt[i], p, x);
        }else if(op == 2) remove(rt[i], read() ^ lst);
        else if(op == 3){
            int l = read() ^ lst, r = read() ^ lst;
            reverse(rt[i], l, r);
        }else{
            int l = read() ^ lst, r = read() ^ lst;
            write(lst = query(rt[i], l, r)), puts("");
        }
    }
    return 0;
}

\[\_EOF\_ \]

posted @ 2021-12-27 14:00  xixike  阅读(58)  评论(2编辑  收藏  举报