洛谷P3835 【模板】可持久化平衡树
题目背景
本题为题目 普通平衡树 的可持久化加强版。
数据已经经过强化
感谢@Kelin 提供的一组hack数据
题目描述
您需要写一种数据结构(可参考题目标题),来维护一些数,其中需要提供以下操作(对于各个以往的历史版本):
-
插入x数
-
删除x数(若有多个相同的数,因只删除一个,如果没有请忽略该操作)
-
查询x数的排名(排名定义为比当前数小的数的个数+1。若有多个相同的数,因输出最小的排名)
-
查询排名为x的数
-
求x的前驱(前驱定义为小于x,且最大的数,如不存在输出-2147483647)
-
求x的后继(后继定义为大于x,且最小的数,如不存在输出2147483647)
和原本平衡树不同的一点是,每一次的任何操作都是基于某一个历史版本,同时生成一个新的版本。(操作3, 4, 5, 6即保持原版本无变化)
每个版本的编号即为操作的序号(版本0即为初始状态,空树)
输入输出格式
输入格式:
第一行包含一个正整数N,表示操作的总数。
接下来每行包含三个整数,第 i 行记为 vi,opti,xi。
vi表示基于的过去版本号( 0≤vi<i ),opti 表示操作的序号( 1≤opt≤6 ), xi 表示参与操作的数值
输出格式:
每行包含一个正整数,依次为各个3,4,5,6操作所对应的答案
输入输出样例
说明
数据范围:
对于28%的数据满足: 1≤n≤10
对于44%的数据满足: 1≤n≤2⋅10^2
对于60%的数据满足: 1≤n≤3⋅10^3
对于84%的数据满足: 1≤n≤10^5
对于92%的数据满足: 1≤n≤2⋅10^5
对于100%的数据满足: 1≤n≤5⋅10^5 , −10^9≤xi≤10^9
经实测,正常常数的可持久化平衡树均可通过,请各位放心
样例说明:
共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<iostream> 2 #include<cstdio> 3 #include<algorithm> 4 #include<cstring> 5 using namespace std; 6 long long read() 7 { 8 long long x=0,f=1; 9 char ch=getchar(); 10 while(ch>'9'||ch<'0') 11 { 12 if(ch=='-') 13 f=-1; 14 ch=getchar(); 15 } 16 while(ch>='0'&&ch<='9') 17 { 18 x=x*10+ch-'0'; 19 ch=getchar(); 20 } 21 return x*f; 22 } 23 const int maxn=5e5+5; 24 struct node 25 { 26 int l,r,v,rd,sum; 27 } e[maxn*50]; 28 int n,num,x,y,opt; 29 int root[maxn]; 30 void update(int i) 31 { 32 if(!i) 33 return ; 34 e[i].sum=e[e[i].l].sum+e[e[i].r].sum+1; 35 } 36 int add(int x) 37 { 38 ++num; 39 e[num].l=e[num].r=0; 40 e[num].sum=1; 41 e[num].v=x; 42 e[num].rd=rand(); 43 return num; 44 } 45 int merge(int x,int y) 46 { 47 if(!x||!y) 48 return x+y; 49 if(e[x].rd>e[y].rd) 50 { 51 int p=++num; 52 e[p]=e[x]; 53 e[p].r=merge(e[p].r,y); 54 update(p); 55 return p; 56 } 57 else 58 { 59 int p=++num; 60 e[p]=e[y]; 61 e[p].l=merge(x,e[p].l); 62 update(p); 63 return p; 64 } 65 } 66 void split(int now,int k,int &x,int &y) 67 { 68 if(now==0) 69 { 70 x=y=0; 71 return ; 72 } 73 if(e[now].v<=k) 74 { 75 x=++num; 76 e[x]=e[now]; 77 split(e[x].r,k,e[x].r,y); 78 update(x); 79 } 80 else 81 { 82 y=++num; 83 e[y]=e[now]; 84 split(e[y].l,k,x,e[y].l); 85 update(y); 86 } 87 } 88 void insert(int &root,int v) 89 { 90 int x=0,y=0,z=0; 91 split(root,v-1,x,y); 92 z=add(v); 93 root=merge(merge(x,z),y); 94 } 95 void del(int &root,int v) 96 { 97 int x=0,y=0,z=0; 98 split(root,v,x,z); 99 split(x,v-1,x,y); 100 y=merge(e[y].l,e[y].r); 101 root=merge(merge(x,y),z); 102 } 103 int rank(int i,int k) 104 { 105 if(k==e[e[i].l].sum+1) 106 return e[i].v; 107 if(k<=e[e[i].l].sum) 108 return rank(e[i].l,k); 109 return rank(e[i].r,k-e[e[i].l].sum-1); 110 } 111 int query(int &root,int v) 112 { 113 int x,y; 114 split(root,v-1,x,y); 115 int ans=e[x].sum+1; 116 root=merge(x,y); 117 return ans; 118 } 119 int pre(int &root,int v) 120 { 121 int x,y,k; 122 split(root,v-1,x,y); 123 if(x==0) 124 return -2147483647; 125 k=e[x].sum; 126 int ans=rank(x,k); 127 root=merge(x,y); 128 return ans; 129 } 130 int nex(int &root,int v) 131 { 132 int x,y,ans; 133 split(root,v,x,y); 134 if(y==0) 135 return 2147483647; 136 ans=rank(y,1); 137 root=merge(x,y); 138 return ans; 139 } 140 int main() 141 { 142 n=read(); 143 for(int i=1; i<=n; i++) 144 { 145 x=read(),opt=read(),y=read(); 146 root[i]=root[x]; 147 if(opt==1) 148 insert(root[i],y); 149 if(opt==2) 150 del(root[i],y); 151 if(opt==3) 152 printf("%d\n",query(root[i],y)); 153 if(opt==4) 154 printf("%d\n",rank(root[i],y)); 155 if(opt==5) 156 printf("%d\n",pre(root[i],y)); 157 if(opt==6) 158 printf("%d\n",nex(root[i],y)); 159 } 160 return 0; 161 }