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

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; 
}

  

posted @ 2019-04-12 18:40 EM-LGH 阅读( ...) 评论( ...) 编辑 收藏
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
持久化splay是一种数据结构,它是对splay树进行修改和查询的一种扩展。在传统的splay树中,对树的修改操作会破坏原有的树结构,而可持久化splay树则允许我们对树进行修改、查询,并且可以保存修改后的每个版本的树结构。 在可持久化splay树中,我们不会直接对原树进行修改,而是通过复制每个节点来创建新的版本。这样,每个版本都可以独立地修改和查询,保留了原有版本的结构和状态。每个节点保存了其左子树和右子树的引用,使得可以在不破坏原有版本的情况下进行修改和查询。 为了实现可持久化splay树,我们可以使用一些技巧,比如引用中提到的哨兵节点和假的父节点和孩子节点。这些技巧可以帮助我们处理根节点的旋转和其他操作。 此外,可持久化splay树还可以与其他数据结构相结合,比如引用中提到的可持久化线段树。这种结合可以帮助我们解决更复杂的问题,比如区间修改和区间查询等。 对于可持久化splay树的学习过程,可以按照以下步骤进行: 1. 理解splay树的基本原理和操作,包括旋转、插入、删除和查找等。 2. 学习如何构建可持久化splay树,包括复制节点、更新版本和保存历史版本等。 3. 掌握可持久化splay树的常见应用场景,比如区间修改和区间查询等。 4. 深入了解与可持久化splay树相关的其他数据结构和算法,比如可持久化线段树等。 在解决问题时,可以使用二分法来确定答案,一般称为二分答案。通过对答案进行二分,然后对每个答案进行检查,以确定最终的结果。这种方法可以应用于很多问题,比如引用中提到的在线询问问题。 综上所述,可持久化splay是一种对splay树进行修改和查询的扩展,可以通过复制节点来创建新的版本,并且可以与其他数据结构相结合解决更复杂的问题。学习过程中可以按照一定的步骤进行,并且可以使用二分法来解决一些特定的问题。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* [[学习笔记]FHQ-Treap及其可持久化](https://blog.csdn.net/weixin_34283445/article/details/93207491)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] - *2* *3* [可持久化数据结构学习笔记](https://blog.csdn.net/weixin_30376083/article/details/99902410)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值