luogu 3835 可持久化平衡树
题目背景
本题为题目 普通平衡树 的可持久化加强版。
数据已经经过强化
感谢@Kelin 提供的一组hack数据
题目描述
您需要写一种数据结构(可参考题目标题),来维护一些数,其中需要提供以下操作(对于各个以往的历史版本):
-
插入x数
-
删除x数(若有多个相同的数,因只删除一个,如果没有请忽略该操作)
-
查询x数的排名(排名定义为比当前数小的数的个数+1。若有多个相同的数,因输出最小的排名)
-
查询排名为x的数
-
求x的前驱(前驱定义为小于x,且最大的数,如不存在输出-2147483647)
-
求x的后继(后继定义为大于x,且最小的数,如不存在输出2147483647)
和原本平衡树不同的一点是,每一次的任何操作都是基于某一个历史版本,同时生成一个新的版本。(操作3, 4, 5, 6即保持原版本无变化)
每个版本的编号即为操作的序号(版本0即为初始状态,空树)
输入格式
第一行包含一个正整数N,表示操作的总数。
接下来每行包含三个整数,第 ii 行记为 v_i, opt_i, x_ivi,opti,xi。
v_ivi表示基于的过去版本号( 0 \leq v_i < i0≤vi<i ),opt_iopti 表示操作的序号( 1 \leq opt \leq 61≤opt≤6 ), x_ixi 表示参与操作的数值
输出格式
每行包含一个正整数,依次为各个3,4,5,6操作所对应的答案
输入输出样例
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
9 1 2 10 3
说明/提示
数据范围:
对于28%的数据满足: 1 \leq n \leq 101≤n≤10
对于44%的数据满足: 1 \leq n \leq 2\cdot {10}^21≤n≤2⋅102
对于60%的数据满足: 1 \leq n \leq 3\cdot {10}^31≤n≤3⋅103
对于84%的数据满足: 1 \leq n \leq {10}^51≤n≤105
对于92%的数据满足: 1 \leq n \leq 2\cdot {10}^51≤n≤2⋅105
对于100%的数据满足: 1 \leq n \leq 5\cdot {10}^51≤n≤5⋅105 , -{10}^9 \leq x_i \leq {10}^9−109≤xi≤109
经实测,正常常数的可持久化平衡树均可通过,请各位放心
样例说明:
共10次操作,11个版本,各版本的状况依次是:
-
[][]
-
[9][9]
-
[3, 9][3,9]
-
[9, 10][9,10]
-
[3, 9][3,9]
-
[9, 10][9,10]
-
[2, 9, 10][2,9,10]
-
[2, 9, 10][2,9,10]
-
[2, 10][2,10]
-
[2, 10][2,10]
-
[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 }