[洛谷P3835]【模板】可持久化平衡树
题目大意:
您需要写一种数据结构(可参考题目标题),来维护一些数,其中需要提供以下操作(对于各个以往的历史版本):
1. 插入x数
2. 删除x数(若有多个相同的数,因只删除一个,如果没有请忽略该操作)
3. 查询x数的排名(排名定义为比当前数小的数的个数+1。若有多个相同的数,因输出最小的排名)
4. 查询排名为x的数
5. 求x的前驱(前驱定义为小于x,且最大的数,如不存在输出-2147483647)
6. 求x的后继(后继定义为大于x,且最小的数,如不存在输出2147483647)
和原本平衡树不同的一点是,每一次的任何操作都是基于某一个历史版本,同时生成一个新的版本。(操作3, 4, 5, 6即保持原版本无变化)
每个版本的编号即为操作的序号(版本0即为初始状态,空树)。
解题思路:
可持久化平衡树,用非旋Treap实现。
和普通Treap其实没什么区别,主要是split和平常写的重量平衡树有点不同,然后每次要新建节点,其他都一样。
C++ Code:
#include<bits/stdc++.h>
#define N 500005
struct node{
int r,ls,rs,s,sz;
}a[N*50];
int rt[N],cnt=0;
inline int readint(){
int c=getchar(),d=0,b=0;
for(;!isdigit(c);c=getchar())b=c=='-';
for(;isdigit(c);c=getchar())d=(d<<3)+(d<<1)+(c^'0');
return b?-d:d;
}
inline void update(int x){
a[x].sz=a[a[x].ls].sz+a[a[x].rs].sz+1;
}
void split(int u,int k,int& x,int& y){
if(!u)x=y=0;
else{
if(a[u].s<=k){
a[x=++cnt]=a[u];
split(a[x].rs,k,a[x].rs,y);
update(x);
}else{
a[y=++cnt]=a[u];
split(a[y].ls,k,x,a[y].ls);
update(y);
}
}
}
int merge(int x,int y){
if(!x||!y)return x|y;
int u;
if(a[x].r<a[y].r){
a[u=++cnt]=a[x];
a[u].rs=merge(a[u].rs,y);
}else{
a[u=++cnt]=a[y];
a[u].ls=merge(x,a[u].ls);
}
update(u);
return u;
}
void Insert(int& root,int w){
int x,y,z;
split(root,w,x,y);
a[z=++cnt]=(node){rand(),0,0,w,1};
root=merge(merge(x,z),y);
}
void Delete(int& root,int w){
int x,y,z;
split(root,w,x,y);
split(x,w-1,x,z);
if(a[z].s==w)
root=merge(merge(x,merge(a[z].ls,a[z].rs)),y);else
root=merge(merge(x,z),y);
}
int getpos(int now,int k){
for(;;){
if(k<=a[a[now].ls].sz)now=a[now].ls;
if(k==a[a[now].ls].sz+1)return now;
if(k>a[a[now].ls].sz)k-=a[a[now].ls].sz+1,now=a[now].rs;
}
}
int kth(int rt,int w){
int x,y,rank;
split(rt,w-1,x,y);
rank=a[x].sz+1;
rt=merge(x,y);
return rank;
}
int find(int rt,int w){
return a[getpos(rt,w)].s;
}
int pre(int rt,int w){
int x,y,ans;
split(rt,w-1,x,y);
if(!x)ans=-2147483647;else
ans=a[x].sz;
if(ans!=-2147483647)
ans=find(x,ans);
rt=merge(x,y);
return ans;
}
int nxt(int rt,int w){
int x,y,ans;
split(rt,w,x,y);
if(!y)ans=2147483647;else
ans=a[y].sz;
if(ans!=2147483647)
ans=find(y,1);
rt=merge(x,y);
return ans;
}
int main(){
srand(20170607);
memset(rt,0,sizeof rt);
memset(a,0,sizeof a);
for(int T=readint(),now=1;now<=T;++now){
int v=readint(),opt=readint(),x=readint();
rt[now]=rt[v];
if(opt==1)Insert(rt[now],x);else
if(opt==2)Delete(rt[now],x);else
if(opt==3)printf("%d\n",kth(rt[now],x));else
if(opt==4)printf("%d\n",find(rt[now],x));else
if(opt==5)printf("%d\n",pre(rt[now],x));else
printf("%d\n",nxt(rt[now],x));
}
return 0;
}

浙公网安备 33010602011771号