• 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\_ \]

  • 相关阅读:
    【转】属性与字段的区别
    学习C/C++的经验谈(转)
    [C++语法] 关键字typedef用法(转)
    让我们习惯在底层用C++宏生成代码 (转)
    C/C++笔试题 (二)【转】
    C/C++笔试题 (三)【转】
    C语言 printf格式控制符 完全解析
    C/C++笔试题 (一)【转】
    C++内存管理详解(转)
    【转】 Source Insight设置
  • 原文地址:https://www.cnblogs.com/xixike/p/15736003.html
Copyright © 2020-2023  润新知