各种平衡树

时间:2022-05-08
本文章向大家介绍各种平衡树,主要内容包括Vector、Splay、FHQ Treap、01 Trie树、Treap、基本概念、基础应用、原理机制和需要注意的事项等,并结合实例形式分析了其使用技巧,希望通过本文能帮助到大家理解应用这部分内容。

记一下自己写的平衡树

方便以后复制粘贴

题目链接

Vector

最快:284ms

 1 #include<cstdio>
 2 #include<vector>
 3 #include<algorithm>
 4 using namespace std;
 5 const int MAXN=100005;
 6 vector<int>v;
 7 int n,opt,x;
 8 inline char nc()
 9 {
10     static char buf[MAXN],*p1=buf,*p2=buf;
11     return p1==p2&&(p2=(p1=buf)+fread(buf,1,MAXN,stdin),p1==p2)?EOF:*p1++;
12 }
13 inline int read()
14 {
15     char c=nc();int x=0,f=1;
16     while(c<'0'||c>'9'){if(c=='-')f=-1;c=nc();}
17     while(c>='0'&&c<='9'){x=x*10+c-'0';c=nc();}
18     return x*f;
19 }
20 int main()
21 {
22     v.reserve(100001);
23     n=read();
24     while(n--)
25     {
26         opt=read();x=read();
27         if(opt==1)    v.insert(lower_bound(v.begin(),v.end(),x),x);
28         if(opt==2)    v.erase (lower_bound(v.begin(),v.end(),x));
29         if(opt==3)    printf("%dn",lower_bound(v.begin(),v.end(),x)-v.begin()+1);
30         if(opt==4)    printf("%dn",v[x-1]);
31         if(opt==5)    printf("%dn",v[lower_bound(v.begin(),v.end(),x)-v.begin()-1]);
32         if(opt==6)    printf("%dn",v[upper_bound(v.begin(),v.end(),x)-v.begin()]);
33     }
34     return 0;
35 }

Splay

最快:128ms

#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
#define ls(x) T[x].ch[0]
#define rs(x) T[x].ch[1]
#define fa(x) T[x].fa
#define root T[0].ch[1]
using namespace std;
const int MAXN=1e5+10,mod=10007,INF=1e9+10;
inline char nc()
{
    static char buf[MAXN],*p1=buf,*p2=buf;
    return p1==p2&&(p2=(p1=buf)+fread(buf,1,MAXN,stdin)),p1==p2?EOF:*p1++;
}
inline int read()
{
    char c=nc();int x=0,f=1;
    while(c<'0'||c>'9'){if(c=='-')f=-1;c=nc();}
    while(c>='0'&&c<='9'){x=x*10+c-'0';c=nc();}
    return x*f;
}
struct node
{
    int fa,ch[2],val,rec,sum;
}T[MAXN];
int tot=0;
void update(int x){T[x].sum=T[ls(x)].sum+T[rs(x)].sum+T[x].rec;}
int ident(int x){return T[fa(x)].ch[0]==x?0:1;}
void connect(int x,int fa,int how){T[fa].ch[how]=x;T[x].fa=fa;}
void rotate(int x)
{
    int Y=fa(x),R=fa(Y);
    int Yson=ident(x),Rson=ident(Y);
    connect(T[x].ch[Yson^1],Y,Yson);
    connect(Y,x,Yson^1);
    connect(x,R,Rson);
    update(Y);update(x);
}
void splay(int x,int to)
{
    to=fa(to);
    while(fa(x)!=to)
    {
        int y=fa(x);
        if(T[y].fa==to) rotate(x);
        else if(ident(x)==ident(y)) rotate(y),rotate(x);
        else rotate(x),rotate(x);
    }
}
int newnode(int v,int f)
{
    T[++tot].fa=f;
    T[tot].rec=T[tot].sum=1;
    T[tot].val=v;
    return tot;
}
void Insert(int x)
{
    int now=root;
    if(root==0) {newnode(x,0);root=tot;}//
    else
    {
        while(1)
        {
            T[now].sum++;
            if(T[now].val==x) {T[now].rec++;splay(now,root);return ;}
            int nxt=x<T[now].val?0:1;
            if(!T[now].ch[nxt])
            {
                int p=newnode(x,now);
                T[now].ch[nxt]=p;
                splay(p,root);return ;
            }
            now=T[now].ch[nxt];
        }        
    }
}
int find(int x)
{
    int now=root;
    while(1)
    {
        if(!now) return 0;
        if(T[now].val==x) {splay(now,root);return now;}
        int nxt=x<T[now].val?0:1;
        now=T[now].ch[nxt];
    }
}
void delet(int x)
{
    int pos=find(x);
    if(!pos) return ;
    if(T[pos].rec>1) {T[pos].rec--,T[pos].sum--;return ;} 
    else
    {
        if(!T[pos].ch[0]&&!T[pos].ch[1]) {root=0;return ;}
        else if(!T[pos].ch[0]) {root=T[pos].ch[1];T[root].fa=0;return ;}
        else
        {
            int left=T[pos].ch[0];
            while(T[left].ch[1]) left=T[left].ch[1];
            splay(left,T[pos].ch[0]);
            connect(T[pos].ch[1],left,1); 
            connect(left,0,1);//
            update(left);
        }
    }
}
int rak(int x)
{
    int now=root,ans=0;
    while(1)
    {
        if(T[now].val==x) return ans+T[T[now].ch[0]].sum+1;
        int nxt=x<T[now].val?0:1;
        if(nxt==1) ans=ans+T[T[now].ch[0]].sum+T[now].rec;
        now=T[now].ch[nxt];
    }
}
int kth(int x)//排名为x的数 
{
    int now=root;
    while(1)
    {
        int used=T[now].sum-T[T[now].ch[1]].sum;
        if(T[T[now].ch[0]].sum<x&&x<=used) {splay(now,root);return T[now].val;}
        if(x<used) now=T[now].ch[0];
        else now=T[now].ch[1],x-=used;
    }
}
int lower(int x)
{
    int now=root,ans=-INF;
    while(now)
    {
        if(T[now].val<x) ans=max(ans,T[now].val);
        int nxt=x<=T[now].val?0:1;//这里需要特别注意 
        now=T[now].ch[nxt];
    }
    return ans;
}
int upper(int x)
{
    int now=root,ans=INF;
    while(now)
    {
        if(T[now].val>x) ans=min(ans,T[now].val);
        int nxt=x<T[now].val?0:1;
        now=T[now].ch[nxt];
    }
    return ans;
}
int main()
{
    #ifdef WIN32
    freopen("a.in","r",stdin);
    #else
    #endif
    int N=read();
    while(N--)
    {
        int opt=read(),x=read();
        if(opt==1) Insert(x);
        else if(opt==2) delet(x);
        else if(opt==3) printf("%dn",rak(x));
        else if(opt==4) printf("%dn",kth(x));
        else if(opt==5) printf("%dn",lower(x));
        else if(opt==6) printf("%dn",upper(x));
    } 
    return 0;
}

FHQ Treap

最快:152ms

#include<iostream>
#include<cstdio>
#include<cstring>
#include<ctime>
#include<cstdlib>
using namespace std;
#define ls T[now].ch[0]
#define rs T[now].ch[1]
const int MAXN=1e6+10;
inline char nc()
{
    static char buf[MAXN],*p1=buf,*p2=buf;
    return p1==p2&&(p2=(p1=buf)+fread(buf,1,MAXN,stdin),p1==p2)?EOF:*p1++;
}
inline int read()
{
    char c=nc();int x=0,f=1;
    while(c<'0'||c>'9'){if(c=='-')f=-1;c=nc();}
    while(c>='0'&&c<='9'){x=x*10+c-'0',c=nc();}
    return x*f;
}
struct node
{
    int ch[2],val,siz,pri;
}T[MAXN];
int tot=0;
int x,y,z,root=0;
int newnode(int v)
{
    T[++tot].siz=1;
    T[tot].val=v;
    T[tot].pri=rand();
    return tot;
}
void update(int now)
{
    T[now].siz=T[ls].siz+T[rs].siz+1;
}
void split(int now,int k,int &x,int &y)
{
    if(!now)  {x=y=0;return ;} 
    if(T[now].val<=k)  x=now,split(rs,k,rs,y);
    else y=now,split(ls,k,x,ls);
    update(now);
}
int merge(int x,int y)
{
    if(!x||!y)    return x+y;
    if(T[x].pri<T[y].pri)
    {
        T[x].ch[1]=merge(T[x].ch[1],y);
        update(x);
        return x;
    }
    else 
    {
        T[y].ch[0]=merge(x,T[y].ch[0]);
        update(y);
        return y;
    }
}
int kth(int now,int x)
{
    while(1)
    {
        if(T[ls].siz>=x)     now=ls;
        else
            if(T[ls].siz+1==x)    return now;
            else     x-=T[ls].siz+1,now=rs;
    }
}
int main()
{
    #ifdef WIN32
    freopen("a.in","r",stdin);
    #else
    #endif
    srand((unsigned)time(NULL));
    int n=read();
    while(n--)
    {
        int opt=read(),val=read();
        if(opt==1)
        {
            split(root,val,x,y);
            root=merge( merge(x,newnode(val)),y );
        }
        else if(opt==2)
        {
            split(root,val,x,z);
            split(x,val-1,x,y);
            y=merge(T[y].ch[0],T[y].ch[1]);
            root=merge( merge(x,y) ,z);
        }
        else if(opt==3)
        {
            split(root,val-1,x,y);
            printf("%dn",T[x].siz+1);
            root=merge(x,y);
        }
        else if(opt==4)
        {
            printf("%dn",T[kth(root,val)].val);
        }
        else if(opt==5)
        {
            split(root,val-1,x,y);
            printf("%dn",T[kth(x,T[x].siz)].val);
            root=merge(x,y);
        }
        else if(opt==6)
        {
            split(root,val,x,y);
            printf("%dn",T[kth(y,1)].val);
            root=merge(x,y);
        }
    }
    return 0;
}

01 Trie树

最快:84ms

 1 #include <cstdio>
 2 const int MAXN=1e6+10,INF=1e7;
 3 int ch[MAXN][2],num[MAXN],tot=2,root=1;
 4 inline char nc()
 5 {
 6     static char buf[MAXN],*p1=buf,*p2=buf;
 7     return p1==p2&&(p2=(p1=buf)+fread(buf,1,MAXN,stdin),p1==p2)?EOF:*p1++;
 8 }
 9 inline int read()
10 {
11     char c=nc();int x=0,f=1;
12     while(c<'0'||c>'9'){if(c=='-')f=-1;c=nc();}
13     while(c>='0'&&c<='9'){x=x*10+c-'0';c=nc();}
14     return x*f;
15 }
16 inline void insert(int x,int val)
17 {
18     x+=INF;
19     for(int i=25,now=root,t; ~i; i--)
20     {
21         if( !(ch[now][ t=x>>i &1 ]) )    ch[now][t]=++tot;
22         num[ now=ch[now][t] ]+=val;
23     }
24 }
25 inline int rak(int x)
26 {
27     x+=INF;
28     int ans=0;
29     for(int i=25,now=root,t; ~i ; i--)
30     {
31         if( (t=x>>i &1) )    
32             ans+=num[ ch[now][0] ];
33         now=ch[now][t];
34     }
35     return ans;
36 }
37 inline int kth(int x)
38 {
39     int ans=0;
40     for(int i=25,now=root; ~i ; i--)
41     {
42         if( x>num[ ch[now][0] ] )    ans|=1<<i,x-=num[ ch[now][0] ],now=ch[now][1];
43         else now=ch[now][0];
44     }
45     return ans-INF;
46 }
47 int main() 
48 {
49     #ifdef WIN32
50     freopen("a.in","r",stdin);
51     #else
52     #endif
53     int n=read();
54     while(n --) 
55     {
56         int x=read(),y=read();
57         if(x==1) insert(y, 1);
58         else if(x==2) insert(y, -1);
59         else if(x==3) printf("%dn", rak(y) + 1);
60         else if(x==4) printf("%dn", kth(y) );
61         else if(x==5) printf("%dn", kth( rak(y) ) );
62         else if(x==6) printf("%dn", kth( rak(y + 1) + 1) );
63     }
64 }

Treap

最快:88ms

  1 #include<iostream>
  2 #include<cstdio>
  3 #include<cstdlib>
  4 #define ls tree[k].l
  5 #define rs tree[k].r
  6 using namespace std;
  7 const int MAXN=1e6+10;
  8 inline char nc()
  9 {
 10     static char buf[MAXN],*p1=buf,*p2=buf;
 11     return p1==p2&&(p2=(p1=buf)+fread(buf,1,MAXN,stdin))?EOF:*p1++;
 12 }
 13 inline int read()
 14 {
 15     char c=nc();int x=0,f=1;
 16     while(c<'0'||c>'9'){if(c=='-')f=-1;c=nc();}
 17     while(c>='0'&&c<='9'){x=x*10+c-'0',c=nc();}
 18     return x*f;
 19 }
 20 struct node
 21 {
 22     int l,r,tot,recy,val,rd;
 23 }tree[MAXN];
 24 int size,root,ans=0;
 25 inline void update(int k)
 26 {
 27    tree[k].tot=tree[ls].tot+tree[rs].tot+tree[k].recy;
 28 }
 29 inline void insert(int &k,int x)
 30 {
 31     if(k==0)
 32     {
 33         ++size;k=size;
 34         tree[size].recy=tree[size].tot=1;
 35         tree[size].val=x;tree[size].rd=rand();return ;
 36     }
 37     tree[k].tot++;
 38     if(tree[k].val==x)    tree[k].recy++;
 39     else if(x < tree[k].val)    insert( ls, x);
 40     else insert( rs , x );
 41 }
 42 inline void LeftRotate(int &k)
 43 {
 44     int R=tree[k].r;
 45     tree[k].r=tree[R].l;
 46     tree[R].l=k;
 47     tree[R].tot=tree[k].tot;
 48     update(k);k=R;
 49 }
 50 inline void RightRotate(int &k)
 51 {
 52     int R=tree[k].l;
 53     tree[k].l=tree[R].r;
 54     tree[R].r=k;
 55     tree[R].tot=tree[k].tot;
 56     update(k);k=R;
 57 }
 58 inline void del(int &k,int x)
 59 {
 60     if(!k)    return ;
 61     if(tree[k].val==x)
 62     {
 63         if(tree[k].recy>1)    {tree[k].recy-=1,tree[k].tot-=1;return; }
 64         if(tree[k].l*tree[k].r==0)    k=tree[k].l+tree[k].r;
 65         else if(tree[ls].rd<tree[rs].rd)    RightRotate(k),del(k,x);
 66         else LeftRotate(k),del(k,x);
 67     }
 68     else if(x>tree[k].val)    tree[k].tot--,del(rs,x);
 69     else tree[k].tot--,del(ls,x);
 70 }
 71 int atrank(int &k,int x)
 72 {
 73     if(k==0)    return 0;
 74     if(tree[k].val==x)    return tree[ls].tot+1;
 75     if(tree[k].val<x)    return atrank(rs,x)+tree[ls].tot+tree[k].recy;
 76     else return atrank(ls,x);
 77 }
 78 int rerand(int k,int x)
 79 {
 80     if(k==0)    return 0;
 81     if(x<=tree[ls].tot)    return rerand(ls,x);
 82     else if(x>tree[ls].tot+tree[k].recy)    return rerand(rs,x-tree[ls].tot-tree[k].recy);
 83     else return tree[k].val;
 84 }
 85 void pred(int k,int x)
 86 {
 87     if(k==0) return ;
 88     if(tree[k].val<x)    ans=k,pred(rs,x);
 89     else pred(ls,x);
 90 }
 91 void succ(int &k,int x)
 92 {
 93     if(k==0) return ;
 94     if(tree[k].val>x)    ans=k,succ(ls,x);
 95     else succ(rs,x);
 96 }
 97 int main()
 98 {
 99     #ifdef WIN32
100     freopen("a.in","r",stdin);
101     #else
102     #endif
103     int n=read();
104     while(n--)
105     {
106         int opt=read(),x=read();ans=0;
107         if(opt==1)  insert(root,x);
108         if(opt==2)  del(root,x);
109         if(opt==3)  printf("%dn",atrank(root,x));
110         if(opt==4)  printf("%dn",rerand(root,x));
111         if(opt==5)  {pred(root,x);printf("%dn",tree[ans].val);}
112         if(opt==6)  {succ(root,x);printf("%dn",tree[ans].val);}
113     }
114 }