luogu 3835 可持久化平衡树

题目背景

本题为题目 普通平衡树 的可持久化加强版。

数据已经经过强化

感谢@Kelin 提供的一组hack数据

题目描述

您需要写一种数据结构(可参考题目标题),来维护一些数,其中需要提供以下操作(对于各个以往的历史版本):

  1. 插入x数

  2. 删除x数(若有多个相同的数,因只删除一个,如果没有请忽略该操作)

  3. 查询x数的排名(排名定义为比当前数小的数的个数+1。若有多个相同的数,因输出最小的排名)

  4. 查询排名为x的数

  5. 求x的前驱(前驱定义为小于x,且最大的数,如不存在输出-2147483647)

  6. 求x的后继(后继定义为大于x,且最小的数,如不存在输出2147483647)

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

每个版本的编号即为操作的序号(版本0即为初始状态,空树)

输入格式

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

接下来每行包含三个整数,第 ii 行记为 v_i, opt_i, x_ivi,opti,xi

v_ivi表示基于的过去版本号( 0 \leq v_i < i0vi<i ),opt_iopti 表示操作的序号( 1 \leq opt \leq 61opt6 ), x_ixi 表示参与操作的数值

输出格式

每行包含一个正整数,依次为各个3,4,5,6操作所对应的答案

输入输出样例

输入 #1
10
0 1 9
1 1 3
1 1 10
2 4 2
3 3 9
3 1 2
6 4 1
6 2 9
8 6 3
4 5 8
输出 #1
9
1
2
10
3

说明/提示

数据范围:

对于28%的数据满足: 1 \leq n \leq 101n10

对于44%的数据满足: 1 \leq n \leq 2\cdot {10}^21n2102

对于60%的数据满足: 1 \leq n \leq 3\cdot {10}^31n3103

对于84%的数据满足: 1 \leq n \leq {10}^51n105

对于92%的数据满足: 1 \leq n \leq 2\cdot {10}^51n2105

对于100%的数据满足: 1 \leq n \leq 5\cdot {10}^51n5105 , -{10}^9 \leq x_i \leq {10}^9109xi109

经实测,正常常数的可持久化平衡树均可通过,请各位放心

样例说明:

共10次操作,11个版本,各版本的状况依次是:

  1. [][]

  2. [9][9]

  3. [3, 9][3,9]

  4. [9, 10][9,10]

  5. [3, 9][3,9]

  6. [9, 10][9,10]

  7. [2, 9, 10][2,9,10]

  8. [2, 9, 10][2,9,10]

  9. [2, 10][2,10]

  10. [2, 10][2,10]

  11. [3, 9][3,9]

  1 #include<bits/stdc++.h>
  2 using namespace std; 
  3 int const inf=2147483647;  
  4 int const N=500000+10;  
  5 int const M=N*50; 
  6 int val[M],sz[M],ch[M][2],key[M],n,sum,cnt,rt[N];    
  7 void inline update(int x){
  8     sz[x]=sz[ch[x][0]]+sz[ch[x][1]]+1;  
  9 }
 10 int inline mr(int v){
 11     int x=++cnt; val[x]=v; sz[x]=1; ch[x][0]=ch[x][1]=0; key[x]=rand(); return x; 
 12 }
 13 void inline copy(int x,int y){
 14     val[x]=val[y]; sz[x]=sz[y]; ch[x][0]=ch[y][0]; ch[x][1]=ch[y][1]; key[x]=key[y];  
 15 }
 16 void split(int now,int k,int &x,int &y){
 17     if(!now) x=y=0;  
 18     else {
 19         if(val[now]<=k){
 20             x=++cnt;copy(x,now);  
 21             split(ch[now][1],k,ch[x][1],y);  
 22             update(x);  
 23         }else{
 24             y=++cnt;copy(y,now); 
 25             split(ch[now][0],k,x,ch[y][0]);  
 26             update(y);  
 27         }
 28     }
 29 }
 30 int merge(int x,int y){
 31     if(!x || !y) return x+y;  
 32     else {
 33         if(key[x]<key[y]){
 34             int t=++cnt;copy(t,x);  
 35             ch[t][1]=merge(ch[x][1],y);  
 36             update(t); return t; 
 37         }else{
 38             int t=++cnt;copy(t,y);  
 39             ch[t][0]=merge(x,ch[y][0]);  
 40             update(t); return t;  
 41         }
 42     }
 43 }
 44 int getkth(int x,int k){
 45     while (x){
 46         if(sz[ch[x][0]]>=k) x=ch[x][0];  
 47         else if(sz[ch[x][0]]+1==k) return val[x];  
 48         else k-=sz[ch[x][0]]+1,x=ch[x][1];  
 49     }
 50 }
 51 void dfs(int x){
 52     if(!x) return;  
 53     dfs(ch[x][0]);
 54     cout<<val[x]<<" ";  
 55     dfs(ch[x][1]); 
 56 }
 57 int main(){
 58     scanf("%d",&n);
 59     int x,y,z,t,opt,v;   
 60     while (n--){    
 61         scanf("%d%d%d",&t,&opt,&v);  
 62         if(opt==1){
 63             split(rt[t],v-1,x,y);  
 64     //        cout<<"###"<<x<<" "<<y<<endl;  
 65             rt[++sum]=merge(merge(x,mr(v)),y);  
 66         //    dfs(rt[sum]);  
 67         //    cout<<endl;  
 68         }
 69         if(opt==2){
 70             split(rt[t],v,x,y);  
 71             split(x,v-1,x,z);  
 72             z=merge(ch[z][0],ch[z][1]);  
 73             rt[++sum]=merge(merge(x,z),y);  
 74         }
 75         if(opt==3){
 76             split(rt[t],v-1,x,y);  
 77             printf("%d\n",sz[x]+1);  
 78             rt[t]=merge(x,y); 
 79             rt[++sum]=rt[t];  
 80         }
 81         if(opt==4){
 82         //    cout<<"nima"<<rt[t]<<" "<<sz[rt[t]]<<endl; 
 83             printf("%d\n",getkth(rt[t],v));  
 84             rt[++sum]=rt[t];  
 85         } 
 86         if(opt==5){
 87             split(rt[t],v-1,x,y);  
 88             if(sz[x]==0) printf("%d\n",-inf);  
 89             else printf("%d\n",getkth(x,sz[x]));  
 90             rt[t]=merge(x,y); 
 91             rt[++sum]=rt[t];   
 92         }
 93         if(opt==6){
 94             split(rt[t],v,x,y);  
 95             if(sz[y]==0) printf("%d\n",inf); 
 96             else printf("%d\n",getkth(y,1));  
 97             rt[t]=merge(x,y);
 98             rt[++sum]=rt[t]; 
 99         }
100     }
101     return 0; 
102 } 
View Code

 

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