本題爲題目 普通平衡樹 的可持久化增強版。html
數據已經通過強化node
感謝@Kelin 提供的一組hack數據ios
您須要寫一種數據結構(可參考題目標題),來維護一些數,其中須要提供如下操做(對於各個以往的歷史版本):數據結構
插入x數ide
刪除x數(如有多個相同的數,因只刪除一個,若是沒有請忽略該操做)spa
查詢x數的排名(排名定義爲比當前數小的數的個數+1。如有多個相同的數,因輸出最小的排名)code
查詢排名爲x的數htm
求x的前驅(前驅定義爲小於x,且最大的數,如不存在輸出-2147483647)blog
求x的後繼(後繼定義爲大於x,且最小的數,如不存在輸出2147483647)get
和本來平衡樹不一樣的一點是,每一次的任何操做都是基於某一個歷史版本,同時生成一個新的版本。(操做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 }