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[maxn],sz[maxn],key[maxn];
    int root[maxn];
    ll sumv[maxn];
    ll lastans;
    void ini(){
        tr=0;
        for(int i=1;i<1000000;++i) trash[++tr]=i;
        tot=1000001;
    }
    int newnode(){
        return tr?trash[tr--]:++tot;
    }
    int cpy(int p){
        int x=newnode();
        sz[x]=sz[p],ls[x]=ls[p],rs[x]=rs[p];
        rev[x]=rev[p],val[x]=val[p],key[x]=key[p],sumv[x]=sumv[p];
        return x;
    }
    void up(int x){
        sz[x]=sz[ls[x]]+sz[rs[x]]+1;
        sumv[x]=sumv[ls[x]]+sumv[rs[x]]+(long long)val[x];
    }
    int New(int v){
        int p=newnode();
        sz[p]=1,ls[p]=rs[p]=0,sumv[p]=val[p]=v,key[p]=rand(),rev[p]=0;
        return p;
    }
    void era(int x){
        sz[x]=ls[x]=rs[x]=rev[x]=val[x]=sumv[x]=key[x]=0;
        trash[++tr]=x;
    }
    void pd(int x){
        if(!x||!rev[x]) return;
        if(rev[x]){
            swap(ls[x],rs[x]);
            if(ls[x]) ls[x]=cpy(ls[x]),rev[ls[x]]^=1;
            if(rs[x]) rs[x]=cpy(rs[x]),rev[rs[x]]^=1;
            rev[x]=0;
        }
    }
    void split(int x,int k,int &l,int &r){
        if(x){
            pd(x);
            if(k<=sz[ls[x]]) {
                r=cpy(x);
                split(ls[r],k,l,ls[r]);
                up(r);
            }
            else {
                l=cpy(x);
                split(rs[l],k-sz[ls[l]]-1,rs[l],r);
                up(l);
            }
        }else l=r=0;
    }
    int mg(int l,int r){
        if(l&&r){
            if(key[l]<key[r]) {
                pd(r),ls[r]=mg(l,ls[r]),up(r);
                return r;
            }else {
                pd(l),rs[l]=mg(rs[l],r),up(l);
                return l;
            }
        }else return l+r;
    }
    void ins(int &rt,int p,int v){
        int x,y;
        split(rt,p,x,y);
        rt=mg(mg(x,New(v)),y);
    }
    void Del(int &rt,int p){
        int x,y,z;
        split(rt,p,x,y),split(x,p-1,x,z),era(z);
        rt=mg(x,y);
    }
    void Rev(int &rt,int L,int R){
        int x,y,z;
        split(rt,R,x,y),split(x,L-1,x,z),rev[z]^=1;
        rt=mg(mg(x,z),y);
    }
    void Q(int &rt,int L,int R){
        int x,y,z;
        split(rt,R,x,y),split(x,L-1,x,z), printf("%lld\n",(lastans=sumv[z]));
        rt=mg(mg(x,z),y);
    }
    int main(){
        ini();
        int n,a=0,b=0;
        scanf("%d",&n);
        for(int opt,v,i=1;i<=n;++i){
            scanf("%d%d",&v,&opt);
            root[i]=root[v];
            scanf("%d",&a),a^=lastans;
            if(opt!=2) scanf("%d",&b),b^=lastans;
            if(opt==1) ins(root[i],a,b);
            if(opt==2) Del(root[i],a);
            if(opt==3) Rev(root[i],a,b);
            if(opt==4) Q(root[i],a,b);
        }
        return 0;
    }
};
int main(){
    //setIO("input");
    fhqtreap::main();
    return 0;
}

  

原文地址:https://www.cnblogs.com/guangheli/p/10697824.html

时间: 2024-08-02 02:56:05

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

平衡树讲解(旋转treap,非旋转treap,splay)

在刷了许多道平衡树的题之后,对平衡树有了较为深入的理解,在这里和大家分享一下,希望对大家学习平衡树能有帮助. 平衡树有好多种,比如treap,splay,红黑树,STL中的set.在这里只介绍几种常用的:treap和splay(其中treap包括旋转treap和非旋转treap). 一.treap treap这个词是由tree和heap组合而成,意思是树上的的堆(其实就是字面意思啦qwq).treap可以说是由二叉搜索树(BST)进化而来,二叉搜索树每个点满足它左子树中所有点权值都比它小,它右子

普通平衡树——非旋转treap

题目: 此为平衡树系列第一道:普通平衡树您需要写一种数据结构,来维护一些数,其中需要提供以下操作:1. 插入x数2. 删除x数(若有多个相同的数,因只删除一个)3. 查询x数的排名(若有多个相同的数,因输出最小的排名)4. 查询排名为x的数5. 求x的前驱(前驱定义为小于x,且最大的数)6. 求x的后继(后继定义为大于x,且最小的数) n<=100000 所有数字均在-107到107内. 输入样例: 10 1 106465 4 1 1 317721 1 460929 1 644985 1 841

[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][

【模板】非旋转Treap

Treap,也叫做树堆,是指有一个随机附加域满足堆的性质的二叉搜索树. 如果一棵二叉搜索树插入节点的顺序是随机的,那我们得到的二叉搜索树在大多数情况下是平衡的,期望高度是log(n). 但有些情况下我们并不能得知所有待插入节点,打乱以后再插入,这时我们需要给二叉搜索树加上一个随机附加域,并使这个随机附加域(优先级)满足堆的性质,以此来实现"乱序插入"的想法,使二叉搜索树保持平衡. Treap可以满足的序列操作: 1,插入一个数x 2,删除一个数x 3,查询x的排名 4,查询排名为x的数

4923: [Lydsy1706月赛]K小值查询 平衡树 非旋转Treap

国际惯例的题面:这种维护排序序列,严格大于的进行操作的题都很套路......我们按照[0,k],(k,2k],(2k,inf)分类讨论一下就好.显然第一个区间的不会变化,第二个区间的会被平移进第一个区间,第三个区间的相对大小不会变化.于是我们直接把第二个区间拆了重构,一个一个插入第一个区间即可.因为每次这样做最少减半,所以每个元素只会被重构log次,复杂度nlog^2n.这种按照值域分离区间的操作,非旋转treap实现起来是最简单的......然而第一次写非旋转treap还是出了一点问题,注意它

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

洛谷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

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

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,

洛谷P3391 【模板】文艺平衡树(Splay)(FHQ Treap)

题目背景 这是一道经典的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