[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% 的数据,N\le 5000N5000。

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

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

假设基于的历史版本的序列长度为 len\ge 1len1,有:
若 opt_i=1opti=1,则 0\le p_i\le len0pilen。
若 opt_i=2opti=2,则 1\le p_i\le len1pilen。
若 opt_i=3opti=3,则 1\le l_i\le r_i\le len1lirilen。
若 opt_i=4opti=4,则 1\le l_i\le r_i\le 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('\n');
                merge(b, b, c);
                merge(root[i], a, b);
                break;
        }
    }
    return 0;
}

 

posted @ 2019-12-28 19:37  Elder_Giang  阅读(181)  评论(0编辑  收藏  举报