[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 5000N≤5000。

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

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

假设基于的历史版本的序列长度为 len\ge 1len≥1,有:
若 opt_i=1opti?=1,则 0\le p_i\le len0≤pi?≤len。
若 opt_i=2opti?=2,则 1\le p_i\le len1≤pi?≤len。
若 opt_i=3opti?=3,则 1\le l_i\le r_i\le len1≤li?≤ri?≤len。
若 opt_i=4opti?=4,则 1\le l_i\le r_i\le len1≤li?≤ri?≤len。

假设基于的历史版本的序列长度为 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;
}

原文地址:https://www.cnblogs.com/ruoruoruo/p/12112811.html

时间: 2024-10-10 07:14:12

[LuoguP5055] 可持久化文艺平衡树的相关文章

luoguP5055 【模板】可持久化文艺平衡树 可持久化非旋转treap

好题. Code: #include<bits/stdc++.h> using namespace std; #define setIO(s) freopen(s".in","r",stdin) namespace fhqtreap{ #define maxn 20000000 #define ll long long int tot,m,tr; int trash[maxn]; int ls[maxn],rs[maxn],rev[maxn],val[m

[题解]bzoj 3223 文艺平衡树

3223: Tyvj 1729 文艺平衡树 Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 3884  Solved: 2235[Submit][Status][Discuss] Description 您需要写一种数据结构(可参考题目标题),来维护一个有序数列,其中需要提供以下操作:翻转一个区间,例如原有序序列是5 4 3 2 1,翻转区间是[2,4]的话,结果是5 2 3 4 1 Input 第一行为n,m n表示初始序列有n个数,这个序列依次

3223: Tyvj 1729 文艺平衡树

3223: Tyvj 1729 文艺平衡树 Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 3473  Solved: 1962[Submit][Status][Discuss] Description 您需要写一种数据结构(可参考题目标题),来维护一个有序数列,其中需要提供以下操作:翻转一个区间,例如原有序序列是5 4 3 2 1,翻转区间是[2,4]的话,结果是5 2 3 4 1 Input 第一行为n,m n表示初始序列有n个数,这个序列依次

BZOJ 3223: Tyvj 1729 文艺平衡树

3223: Tyvj 1729 文艺平衡树 Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 3629  Solved: 2053[Submit][Status][Discuss] Description 您需要写一种数据结构(可参考题目标题),来维护一个有序数列,其中需要提供以下操作:翻转一个区间,例如原有序序列是5 4 3 2 1,翻转区间是[2,4]的话,结果是5 2 3 4 1 Input 第一行为n,m n表示初始序列有n个数,这个序列依次

Tyvj P1729 文艺平衡树 Splay

题目: http://tyvj.cn/p/1729 P1729 文艺平衡树 时间: 1000ms / 空间: 131072KiB / Java类名: Main 背景 此为平衡树系列第二道:文艺平衡树 描述 您需要写一种数据结构(可参考题目标题),来维护一个有序数列,其中需要提供以下操作:翻转一个区间,例如原有序序列是5 4 3 2 1,翻转区间是[2,4]的话,结果是5 2 3 4 1 输入格式 第一行为n,m n表示初始序列有n个数,这个序列依次是(1,2……n-1,n)  m表示翻转操作次数

AC日记——文艺平衡树 洛谷 P3391

文艺平衡树 思路: splay翻转操作模板: 虚拟最左最右端点,然后每次都把l翻转到root,r+2翻转到root的右节点: 然后在r+2的左节点上打标记: 标记需要在旋转,rank,print时下放: 建树需要用完全平衡二叉树: 来,上代码: #include <cstdio> #include <cstring> #include <iostream> #include <algorithm> using namespace std; #define m

P3391 【模板】文艺平衡树(Splay)

题目背景 这是一道经典的Splay模板题--文艺平衡树. 题目描述 您需要写一种数据结构(可参考题目标题),来维护一个有序数列,其中需要提供以下操作:翻转一个区间,例如原有序序列是5 4 3 2 1,翻转区间是[2,4]的话,结果是5 2 3 4 1 输入输出格式 输入格式: 第一行为n,m n表示初始序列有n个数,这个序列依次是(1,2, \cdots n-1,n)(1,2,?n?1,n) m表示翻转操作次数 接下来m行每行两个数 [l,r][l,r] 数据保证 1 \leq l \leq r

BZOJ3223: Tyvj 1729 文艺平衡树 [splay]

3223: Tyvj 1729 文艺平衡树 Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 3595  Solved: 2029[Submit][Status][Discuss] Description 您需要写一种数据结构(可参考题目标题),来维护一个有序数列,其中需要提供以下操作:翻转一个区间,例如原有序序列是5 4 3 2 1,翻转区间是[2,4]的话,结果是5 2 3 4 1 Input 第一行为n,m n表示初始序列有n个数,这个序列依次

bzoj3223Tyvj 1729 文艺平衡树

bzoj3223Tyvj 1729 文艺平衡树 题意: 一个数列,支持区间翻转操作. 题解: splay裸题.注意涉及到区间操作的一般用splay不用treap. 代码: 1 #include <cstdio> 2 #include <algorithm> 3 #include <cstring> 4 #define inc(i,j,k) for(int i=j;i<=k;i++) 5 #define fa(x) nds[x].fa 6 #define ch(x,