bzoj3224Treap

Splay版本的会补。。。

在学了2个小时Splay之后深感Treap的优越

特地又花了20分钟打了个Treap

 

至于这些平衡树的优缺点 可以用平衡方式来直观的感受到

现在平衡树们面对着这样的一个问题:“二叉搜索树退化成O(n)”怎么办

Splay说:下面退不退化我不管 我把要查询的点转到根节点上

替罪羊树说:我看哪块不平衡了 我就把它拍扁重建弄成平衡的

SBT说:我旋转强行让深度为logn

RBT说:我手动给每个点打标签让他们出现各种性质然后旋转

而Treap说:在座的各位都是辣鸡 普通的二叉查找树对于随机数据不是平衡的吗?我随机给每个点分派一个数据 让整棵树对于这个随机数据平衡

Splay&替罪羊树&SBT&RBT:Orz

大概就是这样吧

#include<cstdio>
#include<iostream>
#include<cstdlib>
#include<algorithm>
#include<cmath>
#include<cstring>
#include<vector>
#include<queue>
using namespace std;
const int maxn=100010;
const int inf=1e9;
const int mod=1000000;
inline int read()
{
    int x=0,f=1;
    char ch=getchar();
    while(!isdigit(ch)){if(ch=='0')f=-f;ch=getchar();}
    while(isdigit(ch)){x=10*x+ch-'0';ch=getchar();}
    return x*f;
}
struct Treenode
{
    int l,r,v,rnd,size,w;
}; 
inline int ran()
{
    static int seed=1364684679;
    seed+=(seed<<2)+1;
    return seed;
}
struct Treap
{
    Treenode tr[maxn];
    int root,Size,ans;
    inline void update(int k){tr[k].size=tr[tr[k].l].size+tr[tr[k].r].size+tr[k].w;}
    inline void Leftr(int &k)
    {
        int t=tr[k].r;  
        tr[k].r=tr[t].l;  
        tr[t].l=k;  
        tr[t].size=tr[k].size;  
        update(k);  
        k=t; 
    }
    inline void Rightr(int &k)
    {
        int t=tr[k].l;
        tr[k].l=tr[t].r;
        tr[t].r=k;
        tr[t].size=tr[k].size;
        update(k);
        k=t; 
    }
    inline void insert(int &k,int x)  
    {
        if(k==0)  
        {  
            Size++;  
            k=Size;  
            tr[k].size=tr[k].w=1 ;  
            tr[k].v=x;  
            tr[k].rnd=ran();  
            return;
        }  
        tr[k].size++;  
        if(tr[k].v==x)tr[k].w++;  
        else if(x>tr[k].v)  
        {  
            insert(tr[k].r,x) ;  
            if(tr[tr[k].r].rnd<tr[k].rnd)Leftr(k) ;  
        }
        else   
        {  
            insert(tr[k].l,x) ;  
            if(tr[tr[k].l].rnd<tr[k].rnd)Rightr(k) ;  
        }  
    }
    inline void del(int &k,int x)  
    {  
        if(k==0) return;  
        if(tr[k].v==x)  
        {  
            if(tr[k].w>1) {tr[k].w--,tr[k].size--;return;}  
            if(tr[k].l*tr[k].r==0)k=tr[k].l+tr[k].r;  
            else if(tr[tr[k].l].rnd<tr[tr[k].r].rnd){Rightr(k);del(k,x);}
            else{Leftr(k);del(k,x);}  
        }
        else if(x>tr[k].v){tr[k].size--;del(tr[k].r,x);}
        else{tr[k].size--;del(tr[k].l,x);}  
    }  
    inline int query_rank(int k,int x)
    {
        if(k==0) return 0;  
        if(tr[k].v==x) return tr[tr[k].l].size+1 ;  
        else if(x>tr[k].v) return tr[tr[k].l].size+tr[k].w+query_rank(tr[k].r,x) ;  
        else return query_rank(tr[k].l,x) ;
    }
    inline int query_num(int k,int x)  
    {  
        if(k==0) return 0;  
        if(x<=tr[tr[k].l].size)return query_num(tr[k].l ,x) ;  
        else if(x>tr[tr[k].l].size+tr[k].w)return query_num(tr[k].r,x-tr[tr[k].l].size-tr[k].w);
        else return tr[k].v;  
    }  
    inline void query_pro(int k,int x)  
    {  
        if(k==0)return;  
        if(tr[k].v<x)  
        {  
            ans=k ;  
            query_pro(tr[k].r,x);  
        }
        else query_pro(tr[k].l,x);  
    }  
    inline void query_sub(int k,int x)  
    {  
        if(k==0) return;  
        if(tr[k].v>x)  
        {  
            ans=k;  
            query_sub(tr[k].l,x);  
        }
        else query_sub(tr[k].r,x);  
    }
}treap;

int main()
{
    int n;
    scanf("%d",&n);
    int op,x;
    for(int i=1;i<=n;i++)
    {
        scanf("%d%d",&op,&x);
        if(op==1)treap.insert(treap.root,x);
        if(op==2)treap.del(treap.root,x);
        if(op==3)printf("%d\n",treap.query_rank(treap.root,x));
        if(op==4)printf("%d\n",treap.query_num(treap.root,x));
        if(op==5){treap.ans=0;treap.query_pro(treap.root,x);printf("%d\n",treap.tr[treap.ans].v);}
        if(op==6){treap.ans=0;treap.query_sub(treap.root,x);printf("%d\n",treap.tr[treap.ans].v);}
    }
}
View Code

 

posted @ 2017-11-03 23:24  探险家Mr.H  阅读(327)  评论(0编辑  收藏  举报