luogu P5055 【模板】可持久化文艺平衡树

题目背景

这是一道模板题。

题目描述

您需要写一种数据结构,来维护一个序列,其中需要提供以下操作(对于各个以往的历史版本):

  1. 在第 pp 个数后插入数 xx 。
  2. 删除第 pp 个数。
  3. 翻转区间 [l,r][l,r],例如原序列是 \{5,4,3,2,1\}{5,4,3,2,1},翻转区间 [2,4][2,4] 后,结果是 \{5,2,3,4,1\}{5,2,3,4,1}。
  4. 查询区间 [l,r][l,r] 中所有数的和。

和原本平衡树不同的一点是,每一次的任何操作都是基于某一个历史版本,同时生成一个新的版本(操作 44即保持原版本无变化),新版本即编号为此次操作的序号。

本题强制在线。

输入格式

第一行包含一个正整数 NN,表示操作的总数。

接下来 NN 行,每行前两个整数 v_i,opt_ivi,optiv_ivi 表示基于的过去版本号 (0\le v_i<i)(0vi<i),opt_iopti 表示操作的序号 (1\le opt_i\le 4)(1opti4)。

若 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。

 
可持久化平衡树模板题,需要操作插入,删除,翻转,查询。 
  1 #include<bits/stdc++.h>
  2 using namespace std;
  3 #define setIO(s) freopen(s".in","r",stdin)    
  4 namespace fhqtreap{
  5     #define maxn 20000000   
  6     #define ll long long 
  7     int tot,m,tr;
  8     int trash[maxn]; 
  9     int ls[maxn],rs[maxn],rev[maxn],val[maxn],sz[maxn],key[maxn];  
 10     int root[maxn]; 
 11     ll sumv[maxn];
 12     ll lastans;   
 13     void ini(){
 14         tr=0; 
 15         for(int i=1;i<1000000;++i) trash[++tr]=i; 
 16         tot=1000001; 
 17     }
 18     int newnode(){ 
 19         return tr?trash[tr--]:++tot; 
 20     }
 21     int cpy(int p){   
 22         int x=newnode();     
 23         sz[x]=sz[p],ls[x]=ls[p],rs[x]=rs[p]; 
 24         rev[x]=rev[p],val[x]=val[p],key[x]=key[p],sumv[x]=sumv[p]; 
 25         return x; 
 26     }
 27     void up(int x){
 28         sz[x]=sz[ls[x]]+sz[rs[x]]+1;
 29         sumv[x]=sumv[ls[x]]+sumv[rs[x]]+(long long)val[x]; 
 30     }
 31     int New(int v){
 32         int p=newnode(); 
 33         sz[p]=1,ls[p]=rs[p]=0,sumv[p]=val[p]=v,key[p]=rand(),rev[p]=0; 
 34         return p; 
 35     }
 36     void era(int x){
 37         sz[x]=ls[x]=rs[x]=rev[x]=val[x]=sumv[x]=key[x]=0; 
 38         trash[++tr]=x; 
 39     }
 40     void pd(int x){
 41         if(!x||!rev[x]) return;     
 42         if(rev[x]){
 43             swap(ls[x],rs[x]);
 44             if(ls[x]) ls[x]=cpy(ls[x]),rev[ls[x]]^=1;
 45             if(rs[x]) rs[x]=cpy(rs[x]),rev[rs[x]]^=1; 
 46             rev[x]=0; 
 47         }
 48     }
 49     void split(int x,int k,int &l,int &r){
 50         if(x){
 51             pd(x); 
 52             if(k<=sz[ls[x]]) {
 53                 r=cpy(x);     
 54                 split(ls[r],k,l,ls[r]);  
 55                 up(r); 
 56             }
 57             else {
 58                 l=cpy(x); 
 59                 split(rs[l],k-sz[ls[l]]-1,rs[l],r);   
 60                 up(l);  
 61             }
 62         }else l=r=0; 
 63     }
 64     int mg(int l,int r){
 65         if(l&&r){
 66             if(key[l]<key[r]) {
 67                 pd(r),ls[r]=mg(l,ls[r]),up(r); 
 68                 return r; 
 69             }else {
 70                 pd(l),rs[l]=mg(rs[l],r),up(l); 
 71                 return l; 
 72             }
 73         }else return l+r;     
 74     }         
 75     void ins(int &rt,int p,int v){
 76         int x,y; 
 77         split(rt,p,x,y);         
 78         rt=mg(mg(x,New(v)),y);  
 79     }
 80     void Del(int &rt,int p){      
 81         int x,y,z; 
 82         split(rt,p,x,y),split(x,p-1,x,z),era(z); 
 83         rt=mg(x,y); 
 84     }
 85     void Rev(int &rt,int L,int R){
 86         int x,y,z; 
 87         split(rt,R,x,y),split(x,L-1,x,z),rev[z]^=1; 
 88         rt=mg(mg(x,z),y); 
 89     }
 90     void Q(int &rt,int L,int R){
 91         int x,y,z; 
 92         split(rt,R,x,y),split(x,L-1,x,z), printf("%lld\n",(lastans=sumv[z])); 
 93         rt=mg(mg(x,z),y); 
 94     }
 95     int main(){
 96         ini();
 97         int n,a=0,b=0; 
 98         scanf("%d",&n); 
 99         for(int opt,v,i=1;i<=n;++i){
100             scanf("%d%d",&v,&opt); 
101             root[i]=root[v]; 
102             scanf("%d",&a),a^=lastans; 
103             if(opt!=2) scanf("%d",&b),b^=lastans; 
104             if(opt==1) ins(root[i],a,b); 
105             if(opt==2) Del(root[i],a); 
106             if(opt==3) Rev(root[i],a,b); 
107             if(opt==4) Q(root[i],a,b); 
108         }
109         return 0; 
110     }
111 }; 
112 int main(){
113     //setIO("input"); 
114     fhqtreap::main(); 
115     return 0; 
116 }
View Code

 

posted @ 2019-09-03 20:09  zjxxcn  阅读(284)  评论(0编辑  收藏  举报