zoukankan      html  css  js  c++  java
  • [LuoguP5055] 可持久化文艺平衡树


    若 opt_i=1opti=1,则接下来两个整数 p_i,x_ipi,xi,表示操作为在第 p_ipi 个数后插入数 xx 。
    若 opt_i=2opti=2,则接下来一个整数 p_ipi,表示操作为删除第 p_ipi 个数。
    若 opt_i=3opti=3,则接下来两个整数 l_i,r_ili,ri,表示操作为翻转区间 [l_i,r_i][li,ri]。
    若 opt_i=4opti=4,则接下来两个整数 l_i,r_ili,ri,表示操作为查询区间 [l_i,r_i][li,ri] 的和。

    强制在线规则:
    令当前操作之前的最后一次 44 操作的答案为 lastanslastans(如果之前没有 44 操作,则 lastans=0lastans=0)。
    则此次操作的 p_i,x_ipi,xi 或 l_i,r_ili,ri 均按位异或上 lastanslastans 即可得到真实的 p_i,x_ipi,xi 或 l_i,r_ili,ri

    输出格式

    对于每个序号为 44 的查询操作,输出一行一个数表示区间的和。

    输入输出样例

    输入 #1
    10
    0 1 0 1
    1 1 1 2
    2 4 1 2
    3 1 2 0
    4 4 2 1
    5 3 5 7
    6 4 5 6
    4 1 7 1
    8 3 4 6
    9 4 4 1
    输出 #1
    3
    4
    5
    10

    说明/提示

    强制在线:以下针对 p_i,x_i,l_i,r_ipi,xi,li,ri 的限制均是按位异或 lastanslastans 后的限制。

    对于 30\%30% 的数据,Nle 5000N5000。

    对于另外 30\%30% 的数据,v_i=i-1vi=i1。

    对于 100\%100% 的数据,1le Nle 2 imes 10^51N2×105,-10^6<x_i<10^6106<xi<106。

    假设基于的历史版本的序列长度为 lenge 1len1,有:
    若 opt_i=1opti=1,则 0le p_ile len0pilen。
    若 opt_i=2opti=2,则 1le p_ile len1pilen。
    若 opt_i=3opti=3,则 1le l_ile r_ile len1lirilen。
    若 opt_i=4opti=4,则 1le l_ile r_ile len1lirilen。

    假设基于的历史版本的序列长度为 00,有:
    opt_i=1opti=1,p_i=0pi=0。

     
     
    果然期末考试前最好的解压方法就是码数据结构。。
     
    感觉和主席树有异曲同工之妙(虽然我早就把主席树忘光了)
    写的可持久化fhq treap
    注意只用在split的时候新建,merge不需要再新建了
    pushdown也要记得新建
    注意long long
    #include <bits/stdc++.h>
    using namespace std;
    inline long long read(){
        long long f = 1, n = 0;
        char ch = getchar();
        while(!isdigit(ch)){
            if(ch == '-') f = -1;
            ch = getchar();
        }
        while(isdigit(ch)){
            n = (n << 1) + (n << 3) + (ch ^ 48);
            ch = getchar();
        }
        return f * n;
    }
    template<typename T>
    inline void output(T x){
        if(x < 0){
            putchar('-');
            output(-x);
        }
        else{
            if(x > 9) output(x / 10);
            putchar(x % 10 + 48);
        }
    }
    const int maxn = 200000 + 10;
    class Tree{
    public:
        Tree(){
            size = 0;
            sum = val = 0;
            ls = rs = 0;
        }
        Tree(int val): val(val){
            ls = rs = 0;
            size = 1;
            sum = val;
            pri = rand();
            tag = false;
        }
        int ls, rs, size, val, pri;
        long long sum;
        bool tag;
    }tree[maxn << 7];
    int root[maxn], tcnt = 0;
    inline int newnode(int val){
        tree[++tcnt] = Tree(val);
        return tcnt;
    }
    inline int copynode(int x){
        tree[++tcnt] = tree[x];
        return tcnt;
    }
    inline void pushup(int x){
        tree[x].size = tree[tree[x].ls].size + tree[tree[x].rs].size + 1;
        tree[x].sum = tree[tree[x].ls].sum + tree[tree[x].rs].sum + tree[x].val;
    }
    inline void pushdown(int x){
        if(tree[x].tag){
            if(tree[x].ls) tree[x].ls = copynode(tree[x].ls);
            if(tree[x].rs) tree[x].rs = copynode(tree[x].rs);
            swap(tree[x].ls, tree[x].rs);
            tree[tree[x].ls].tag ^= 1;
            tree[tree[x].rs].tag ^= 1;
            tree[x].tag = false;
        }
    }
    void split(int x, int &a, int &b, int k){
        if(!x){
            a = b = 0;
            return;
        }
        pushdown(x);
        if(tree[tree[x].ls].size + 1 <= k){
            a = copynode(x);
            split(tree[x].rs, tree[a].rs, b, k - tree[tree[x].ls].size - 1);
            pushup(a);
        }
        else{
            b = copynode(x);
            split(tree[x].ls, a, tree[b].ls, k);
            pushup(b);
        }
    }
    void merge(int &x, int a, int b){
        if(!a || !b){
            x = a | b;
            return;
        }
        pushdown(a); pushdown(b);
        if(tree[a].pri < tree[b].pri){
            x = a;
            merge(tree[x].rs, tree[a].rs, b);
            pushup(x);
        }
        else{
            x = b;
            merge(tree[x].ls, a, tree[b].ls);
            pushup(x);
        }
    }
    int main(){
        srand(19260817);
        int n = read();
        root[0] = 0;
        int v, opt, a, b, c;
        long long p, x, l, r, lastans = 0;
        for(int i = 1; i <= n; i++){
            v = read(); opt = read();
            switch(opt){
                case 1:
                    p = read() ^ lastans; x = read() ^ lastans;
                    split(root[v], a, b, p);
                    merge(a, a, newnode(x));
                    merge(root[i], a, b);
                    break;
                case 2:
                    p = read() ^ lastans;
                    split(root[v], a, b, p - 1);
                    split(b, b, c, 1);
                    merge(root[i], a, c);
                    break;
                case 3:
                    l = read() ^ lastans; r = read() ^ lastans;
                    split(root[v], a, b, l - 1);
                    split(b, b, c, r - l + 1);
                    tree[b].tag = 1;
                    merge(b, b, c);
                    merge(root[i], a, b);
                    break;
                case 4:
                    l = read() ^ lastans; r = read() ^ lastans;
                    split(root[v], a, b, l - 1);
                    split(b, b, c, r - l + 1);
                    output(lastans = tree[b].sum); putchar('
    ');
                    merge(b, b, c);
                    merge(root[i], a, b);
                    break;
            }
        }
        return 0;
    }
  • 相关阅读:
    MCU开发之I2C通信
    hibernate特殊的映射
    Hibernate使用
    css设置让a标签充满整个li
    margin
    border属性
    列表
    链接样式
    相机内参外参
    tmux
  • 原文地址:https://www.cnblogs.com/ruoruoruo/p/12112811.html
Copyright © 2011-2022 走看看