【洛谷P3835】【模板】—可持久化平衡树(可持久化FHQ_Treap)
其实感觉和主席树没什么区别,考虑到期望的树高大约为
所以每次只会有被改变
不变的指向儿子就可以了
注意引用地址符
#include<bits/stdc++.h>
using namespace std;
inline int read(){
char ch=getchar();
int res=0,f=1;
while(!isdigit(ch)){if(ch=='-')f=-f;ch=getchar();}
while(isdigit(ch))res=(res<<3)+(res<<1)+(ch^48),ch=getchar();
return res*f;
}
const int inf=2147483647;
const int N=500005;
const int Log=50;
int son[N*Log][2],val[N*Log],key[N*Log],siz[N*Log];
int rt[N],n,tot;
#define lc(u) son[u][0]
#define rc(u) son[u][1]
void write(int x){
if(lc(x))write(lc(x));
cout<<val[x]<<" ";
if(rc(x))write(rc(x));
}
inline int addnode(int v){
int u=++tot;
siz[u]=1,key[u]=rand();
val[u]=v;return tot;
}
inline void pushup(int u){
siz[u]=siz[lc(u)]+siz[rc(u)]+1;
}
inline void copy(int r1,int r2){
siz[r1]=siz[r2],lc(r1)=lc(r2),rc(r1)=rc(r2),key[r1]=key[r2],val[r1]=val[r2];
}
void merge(int &u,int r1,int r2){
if(!r1||!r2){u=r1+r2;return;}
if(key[r1]<key[r2]){
u=++tot,copy(u,r1);
merge(rc(u),rc(r1),r2);
}
else {
u=++tot,copy(u,r2);
merge(lc(u),r1,lc(r2));
}
pushup(u);
}
void split(int u,int v,int &r1,int &r2){
if(!u){r1=r2=0;return;}
else{
if(val[u]<=v){
r1=++tot,copy(r1,u);
split(rc(u),v,rc(r1),r2);
pushup(r1);
}
else{
r2=++tot,copy(r2,u);
split(lc(u),v,r1,lc(r2));
pushup(r2);
}
}
}
inline void insert(int &root,int v){
int r1,r2,u=addnode(v);
split(root,v,r1,r2);
merge(r1,r1,u),merge(root,r1,r2);
}
inline void delet(int &root,int v){
int r1,r2,r3;
split(root,v,r1,r2);
split(r1,v-1,r1,r3);
merge(r3,lc(r3),rc(r3));
merge(r1,r1,r3);
merge(root,r1,r2);
}
inline int getrk(int root,int k){
int r1,r2;
split(root,k-1,r1,r2);
int res=siz[r1]+1;
return res;
}
inline int kth(int u,int k){
while(1){
if(siz[lc(u)]>=k)u=lc(u);
else if(siz[lc(u)]+1==k)return val[u];
else k-=siz[lc(u)]+1,u=rc(u);
}
}
inline int pre(int root,int k){
int r1,r2;
split(root,k-1,r1,r2);
if(!r1)return -inf;
int u=r1;
while(rc(u))u=rc(u);
return val[u];
}
inline int nxt(int root,int k){
int r1,r2;
split(root,k,r1,r2);
if(!r2)return inf;
int u=r2;
while(lc(u))u=lc(u);
return val[u];
}
int main(){
srand(20030224);
n=read();
for(int i=1;i<=n;i++){
int pos=read(),op=read(),x=read();
rt[i]=rt[pos];
switch(op){
case 1:insert(rt[i],x);break;
case 2:delet(rt[i],x);break;
case 3:cout<<getrk(rt[i],x)<<'\n';break;
case 4:cout<<kth(rt[i],x)<<'\n';break;
case 5:cout<<pre(rt[i],x)<<'\n';break;
case 6:cout<<nxt(rt[i],x)<<'\n';break;
}
}
}