const int N=2e5;
const int INF=1e9+7;
int cnt=0;
int root;
int lc[N]={0};
int rc[N]={0};
int val[N]={0};//键值为多少。
int siz[N]={0};
int fix[N]={0};//稳定函数,目的是让这颗平衡树比较平衡。
int s[N]={0};//平衡树是要按照当前键值建树的所以有可能出现相同的权重,于是记录在同一个数组内。
struct Treap{//Actually Treap means the SBT+Heap
inline void pushup(int o){
siz[o]=siz[lc[o]]+siz[rc[o]]+s[o];
}
inline int newnode(int x=0){
siz[++cnt]=1;
val[cnt]=x;
fix[cnt]=rand()%12138;
s[cnt]=1;
lc[cnt]=rc[cnt]=0;
return cnt;
}
//merge is just like the Liftist_Tree's merge
//But because of the fix_Arr
//There is no need a dis_Arr to balance the complexity
inline int merge(int A,int B){
if(!A||!B){
return A+B;
}
int x;
if(fix[A]<fix[B]){//Balance the tree
x=A;
rc[x]=merge(rc[x],B);
}
else{
x=B;
lc[x]=merge(A,lc[x]);
}
pushup(x);
return x;
}
//The 'split' just will split the Tree
//split the Tree o into A and B according to thre Rank k
//with A has the rank k
inline void split(int &A,int &B,int o,int k){
if(!o){
A=B=0;
return ;
}
if(k<=siz[lc[o]]){//means that the kth are just at the left
B=o;
split(A,lc[o],lc[o],k);
}
else{
A=o;
split(rc[o],B,rc[o],k-siz[lc[o]]-s[o]);//remember that this should delete the s[o],maybe the key is just the o
}
pushup(o);//We change the structure of the tree
//So we shall pushup it;
}
//the meaning of the rank is that
//give you the sum of the number
//question the rank of it
int rank(int o,int x){
if(o==0)
return 0;
if(x==val[o])
return siz[lc[o]]+1;
if(x<val[o]){
return rank(lc[o],x);
}
return rank(rc[o],x)+s[o]+siz[lc[o]];
}
//the meaning of the Kth is that
//give you the rank of the number
//question the number of it
int kth(int o,int k){
if(k>=siz[lc[o]]+1&&k<=siz[lc[o]]+s[o]){
return val[o];
}
//judge whether the Kth is just the value of the o
//remember that the sum of the o is not only one
if(k<=siz[lc[o]]){
return kth(lc[o],k);
}
return kth(rc[o],k-siz[lc[o]]-s[o]);
}
//The 'insert' just means insert a sum to the Treap
void insert(int &o,int x){
// cout<<"working"<<endl;
if(!o){//If the tree is empty just build the tree whatever it is
o=newnode(x);
return;
}
// cout<<"working"<<endl;
int k=rank(o,x);
//get the rank
int a,b,c;
//split the tree into three pieces
//the a is the lc
//the b is the kth
//the c is the rc
split(a,c,o,k);
split(a,b,a,k-1);
//If the sum of the key has already pushed into the heap
//just change the sum_cnt of it
if(val[b]==x){
s[b]++;
pushup(b);
o=merge(a,merge(b,c));
}
else{//If not create a new Node and merge it into the Heap
o=merge(a,merge(b,newnode(x)));//At the back of the old Kth
o=merge(o,c);
}
}
void del(int x){
int k=rank(root,x);
int a,b,c;
split(a,b,root,k-1);
//At now the b just is the x
//The reason why is that k is the lowest rank of x
//So that means that the precursor of x must at a
split(b,c,b,1);
if(s[b]>1){
s[b]--;
pushup(b);
root=merge(a,merge(b,c));
}
else{
root=merge(a,c);
}
}
//'pred' is a function to get the precursor of x
int pred(int o,int x){
if(!o)
return -INF;
if(x<=val[o])
return pred(lc[o],x);
int ret=pred(rc[o],x);
return val[o]>ret?val[o]:ret;
}
//'succ' is just a function to get the succeed of x
int succ(int o,int x){
if(!o)
return INF;
if(x>=val[o])
return succ(rc[o],x);
int ret=succ(lc[o],x);
return val[o]<ret?val[o]:ret;
}
void debug(int o){
if(!o)
return ;
debug(lc[o]);
printf("%d-%d",val[o],s[o]);
debug(rc[o]);
}
}T;
模板 (带注释)不带旋转的树堆(可持久化)Treap
最新推荐文章于 2019-11-26 21:48:48 发布