[模板]普通平衡树

Posted si-rui-yang

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[模板]普通平衡树相关的知识,希望对你有一定的参考价值。

 

 

技术分享图片
#include<iostream>
#include<cstring>
#include<cstdio>
#include<algorithm>
#include<cmath>
#include<ctime>
#include<climits>
using namespace std;
inline int read(){
    int f=1,ans=0;char c=getchar();
    while(c<0||c>9){if(c==-)f=-1;c=getchar();}
    while(c>=0&&c<=9){ans=ans*10+c-0;c=getchar();}
    return f*ans;
}
const int N=300001;
struct node{
    int l,r,cnt,num,size,rnk;
}tr[N];
int n,root,tot;
void update(int k){
    tr[k].size=tr[k].cnt;
    tr[k].size+=tr[tr[k].l].size;
    tr[k].size+=tr[tr[k].r].size;return;
}
void zag(int &k){
    int tp=tr[k].l;
    tr[k].l=tr[tp].r;
    tr[tp].r=k;
    tr[tp].size=tr[k].size;
    update(k);
    k=tp;
    return;
}
void zig(int &k){
    int tp=tr[k].r;
    tr[k].r=tr[tp].l;
    tr[tp].l=k;
    tr[tp].size=tr[k].size;
    update(k);
    k=tp;
    return;
}
void insert(int x,int &k){
    if(k==0){
        k=++tot;
        tr[k].cnt=tr[k].size=1;tr[k].num=x;
        tr[k].rnk=rand();
        return;
    }
    tr[k].size++;
    if(x==tr[k].num){tr[k].cnt++;return;}
    if(x<tr[k].num){
        insert(x,tr[k].l);
        if(tr[tr[k].l].rnk<tr[k].rnk)zag(k);
    }else{
        insert(x,tr[k].r);
        if(tr[tr[k].r].rnk<tr[k].rnk) zig(k);
    }
    return;
}
void del(int x,int &k){
    if(x==tr[k].num){
        if(tr[k].cnt>1){tr[k].size--,tr[k].cnt--;return;}
        if(tr[k].l*tr[k].r==0) {k=tr[k].l+tr[k].r;return;}
        if(tr[tr[k].l].rnk<tr[tr[k].r].rnk){zag(k);del(x,k);return;}
        else{zig(k);del(x,k);return;}
    }
    tr[k].size--;
    if(x<tr[k].num) del(x,tr[k].l);
    else del(x,tr[k].r);
    return;
}
int rank_x(int x,int k){
    if(x==tr[k].num) return tr[tr[k].l].size+1;
    if(x<tr[k].num) return rank_x(x,tr[k].l);
    return tr[tr[k].l].size+tr[k].cnt+rank_x(x,tr[k].r);
}
int rank(int x,int k){
    if(k==0) return 0;
    if(tr[tr[k].l].size<x&&tr[tr[k].l].size+tr[k].cnt>=x) return tr[k].num;
    if(x<=tr[tr[k].l].size) return rank(x,tr[k].l);
    return rank(x-tr[tr[k].l].size-tr[k].cnt,tr[k].r);
}
int pre(int x,int k){
    if(k==0) return INT_MIN;
    if(x<=tr[k].num) return pre(x,tr[k].l);
    return max(tr[k].num,pre(x,tr[k].r));
}
int nex(int x,int k){
    if(k==0) return INT_MAX;
    if(x>=tr[k].num) return nex(x,tr[k].r);
    return min(tr[k].num,nex(x,tr[k].l));
} 
int main(){
    srand(time(0));
    n=read();
    while(n--){
        int opt=read(),x=read();
        if(opt==1) insert(x,root);
        if(opt==2) del(x,root);
        if(opt==3) printf("%d
",rank_x(x,root));
        if(opt==4) printf("%d
",rank(x,root));
        if(opt==5) printf("%d
",pre(x,root));
        if(opt==6) printf("%d
",nex(x,root));
    }
    return 0;
}
View Code

 

以上是关于[模板]普通平衡树的主要内容,如果未能解决你的问题,请参考以下文章

Luogu P3369 模板普通平衡树

P3369 模板普通平衡树 题解(Splay)

模板普通平衡树

BZOJ 3223 普通平衡树 | 平衡树模板

LG3369 模板普通平衡树

题解 P3369 模板普通平衡树(Treap/SBT)