今天学习了一下非旋
Treap
听说效率很高而且可持久化(一脸懵逼
QAQ
) 非旋Treap主要是两个操作
split
和
merge
下面简单描述一下(得先会
Treap
啊 )
val
:点的值
key
:
rand
的值
split
: 就是我们把原
Treap
拆成两个
Treap
x,y
比如以
value
为分界线 小于他的在
x
里,大于他的在
void split(int now,int<r,int&rtr,int value){
if(!now){
ltr=rtr=0;
return;
}
(data[now].val<=value)?(ltr=now,split(data[now].ch[1],data[ltr].ch[1],rtr,value)):(rtr=now,split(data[now].ch[0],ltr,data[rtr].ch[0],value));
up(now);
}
对于当前的
x,y
要是
x
的
void merge(int&now,int s,int b){
if(!s||!b){
now=s+b;
return;
}
(data[s].key<data[b].key)?(now=s,merge(data[now].ch[1],data[s].ch[1],b)):(now=b,merge(data[now].ch[0],s,data[b].ch[0]));
up(now);
}
具体的其他操作基本上都是建立在这两个操作上的
我们以模板题P3369 【模板】普通平衡树(Treap/SBT) 为例
直接上代码<( ̄▽ ̄)/
#include<bits/stdc++.h>
#define bug(x) cout<<(#x)<<" "<<(x)<<endl
#define ll long long
#define inf INT_MAX
using namespace std;
const int N=1e5+5;
inline int read(){
int x=0,f=1;char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
return x*f;
}
struct Treap{
int val,key,sz;
int ch[2];
}data[N*2];
int m,rt,tot;
void make_data(int&now,int value){
data[++tot].val=value,data[tot].key=rand(),data[tot].sz=1,data[tot].ch[0]=data[tot].ch[1]=0;
now=tot;
}
void up(int now){
data[now].sz=data[data[now].ch[0]].sz+data[data[now].ch[1]].sz+1;
}
void merge(int&now,int s,int b){
if(!s||!b){
now=s+b;
return;
}
(data[s].key<data[b].key)?(now=s,merge(data[now].ch[1],data[s].ch[1],b)):(now=b,merge(data[now].ch[0],s,data[b].ch[0]));
up(now);
}
void split(int now,int<r,int&rtr,int value){
if(!now){
ltr=rtr=0;
return;
}
(data[now].val<=value)?(ltr=now,split(data[now].ch[1],data[ltr].ch[1],rtr,value)):(rtr=now,split(data[now].ch[0],ltr,data[rtr].ch[0],value));
up(now);
}
void insert(int value){
int x=0,y=0,z=0;
make_data(z,value);
split(rt,x,y,value);
merge(x,x,z);
merge(rt,x,y);
}
void del(int value){
int x=0,y=0,z=0;
split(rt,x,y,value);
split(x,x,z,value-1);
merge(z,data[z].ch[0],data[z].ch[1]);
merge(x,x,z),merge(rt,x,y);
}
void rnk(int value){
int x=0,y=0;
split(rt,x,y,value-1);
printf("%d\n",data[x].sz+1);
merge(rt,x,y);
}
void find(int now,int x){
while(data[data[now].ch[0]].sz+1!=x){
if(data[data[now].ch[0]].sz>=x) now=data[now].ch[0];
else x-=data[data[now].ch[0]].sz+1,now=data[now].ch[1];
}
printf("%d\n",data[now].val);
}
void pre(int value){
int x=0,y=0;
split(rt,x,y,value-1);
find(x,data[x].sz);
merge(rt,x,y);
}
void sub(int value){
int x=0,y=0;
split(rt,x,y,value);
find(y,1);
merge(rt,x,y);
}
int main(){
#ifdef Devil_Gary
freopen("in.txt","r",stdin);
#endif
srand(233),m=read();
data[0].key=inf,data[0].val=inf,data[0].sz=0;
for(int i=1,op,x;i<=m;i++) {
op=read(),x=read();
if(op==1) insert(x);
else if(op==2) del(x);
else if(op==3) rnk(x);
else if(op==4) find(rt,x);
else if(op==5) pre(x);
else if(op==6) sub(x);
}
return 0;
}