可持久化无旋Treap
今天又学习了可持久化非旋Treap,其实很简单,将普通的非旋Treap持久化一遍就行了。具体来说,就是将每次操作后得到的树记录下来,每次需要改变一个点的信息时,将原有的点的信息记录下来,建一个新点去更改它的信息。
其实持久化的过程与线段树的持久化相似。
其实打出来跟普通的非旋Treap差不多,加几个改点的步骤即可。
非旋Treap学习见此处:非旋Treap学习
模板
下面是模板。其实与非旋Treap差不多,可以跳过。
分裂
void split(int now,int k,int &x,int &y){
if(!now){
x=y=0;
return ;
}
if(k<val[now]){
y=++tot;newpoint(y,now);
split(son[y][0],k,x,son[y][0]);
updata(y);
}
else{
x=++tot;newpoint(x,now);
split(son[x][1],k,son[x][1],y);
updata(x);
}
}
合并
int merge(int a,int b){
if(!a||!b) return a+b;
if(rnd[a]>rnd[b]){
int p=++tot;newpoint(p,a);
son[p][1]=merge(son[p][1],b);
updata(p);return p;
}
int p=++tot;newpoint(p,b);
son[p][0]=merge(a,son[p][0]);
updata(p);return p;
}
插入
void Insert(int &rt,int w){
int xa=0,ya=0,z=0;split(rt,w,xa,ya);
z=newnode(w);rt=merge(merge(xa,z),ya);
}
删除
void Delete(int &rt,int w){
int xa=0,ya=0,z=0,xb=0,yb=0;
split(rt,w,xa,ya);split(xa,w-1,xb,yb);
rt=merge(merge(xb,son[yb][0]),merge(son[yb][1],ya));
}
查询排名
int rankth(int &rt,int w){
int xa,ya;split(rt,w-1,xa,ya);
int res=siz[xa]+1;rt=merge(xa,ya);
return res;
}
查询第k小
int kth(int p,int w){
if(w==siz[son[p][0]]+1) return val[p];
if(w<=siz[son[p][0]]) return kth(son[p][0],w);
return kth(son[p][1],w-siz[son[p][0]]-1);
}
前驱与后继
int pre(int &rt,int w){
int xa,ya;split(rt,w-1,xa,ya);
if(!xa) return -INF;
int k=siz[xa],res=kth(xa,k);
rt=merge(xa,ya);return res;
}
int nxt(int &rt,int w){
int xa,ya;split(rt,w,xa,ya);
if(!ya) return INF;
int res=kth(ya,1);rt=merge(xa,ya);
return res;
}
例题
还是去看一看【模板】可持久化平衡树吧!
源码
#include<cstdio>
#include<cmath>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<queue>
#define MAXN 500005
using namespace std;
typedef long long LL;
const int INF=0x7f7f7f7f;
#define gc() getchar()
int son[MAXN*50][2],tot,rot[MAXN];
int rnd[MAXN*50],siz[MAXN*50],n;
int val[MAXN*50];
template<typename _T>
inline void read(_T &x){
_T f=1;x=0;char s=gc();
while(s>'9'||s<'0'){if(s=='-')f=-1;s=gc();}
while(s>='0'&&s<='9'){x=(x<<3)+(x<<1)+(s^48);s=gc();}
x*=f;
}
void updata(int x){
siz[x]=siz[son[x][0]]+siz[son[x][1]]+1;
}
int newnode(int x){
int p=++tot;
val[p]=x;siz[p]=1;rnd[p]=rand();
son[p][0]=son[p][1]=0;updata(p);
return p;
}
void newpoint(int a,int b){
val[a]=val[b];siz[a]=siz[b];rnd[a]=rnd[b];
son[a][0]=son[b][0];son[a][1]=son[b][1];
updata(a);
}
int merge(int a,int b){
if(!a||!b) return a+b;
if(rnd[a]>rnd[b]){
int p=++tot;newpoint(p,a);
son[p][1]=merge(son[p][1],b);
updata(p);return p;
}
int p=++tot;newpoint(p,b);
son[p][0]=merge(a,son[p][0]);
updata(p);return p;
}
void split(int now,int k,int &x,int &y){
if(!now){
x=y=0;
return ;
}
if(k<val[now]){
y=++tot;newpoint(y,now);
split(son[y][0],k,x,son[y][0]);
updata(y);
}
else{
x=++tot;newpoint(x,now);
split(son[x][1],k,son[x][1],y);
updata(x);
}
}
void Insert(int &rt,int w){
int xa=0,ya=0,z=0;split(rt,w,xa,ya);
z=newnode(w);rt=merge(merge(xa,z),ya);
}
void Delete(int &rt,int w){
int xa=0,ya=0,z=0,xb=0,yb=0;
split(rt,w,xa,ya);split(xa,w-1,xb,yb);
rt=merge(merge(xb,son[yb][0]),merge(son[yb][1],ya));
}
int rankth(int &rt,int w){
int xa,ya;split(rt,w-1,xa,ya);
int res=siz[xa]+1;rt=merge(xa,ya);
return res;
}
int kth(int p,int w){
if(w==siz[son[p][0]]+1) return val[p];
if(w<=siz[son[p][0]]) return kth(son[p][0],w);
return kth(son[p][1],w-siz[son[p][0]]-1);
}
int pre(int &rt,int w){
int xa,ya;split(rt,w-1,xa,ya);
if(!xa) return -INF;
int k=siz[xa],res=kth(xa,k);
rt=merge(xa,ya);return res;
}
int nxt(int &rt,int w){
int xa,ya;split(rt,w,xa,ya);
if(!ya) return INF;
int res=kth(ya,1);rt=merge(xa,ya);
return res;
}
signed main()
{
read(n);
for(int i=1;i<=n;i++){
int v,opt,x;read(v);read(opt);read(x);rot[i]=rot[v];
if(opt==1) Insert(rot[i],x);
if(opt==2) Delete(rot[i],x);
if(opt==3) printf("%d\n",rankth(rot[i],x));
if(opt==4) printf("%d\n",kth(rot[i],x));
if(opt==5) printf("%d\n",pre(rot[i],x));
if(opt==6) printf("%d\n",nxt(rot[i],x));
}
return 0;
}