码迷,mamicode.com
首页 > 其他好文 > 详细

BZOJ_3224_普通平衡树(Treap)

时间:2016-05-11 23:19:23      阅读:152      评论:0      收藏:0      [点我收藏+]

标签:

描述


Treap模板题.支持如下几种操作:

1.插入;

2.删除;

3.rank(x);

4.kth(k);

5.pre(x);

6.suc(x);

 

分析


写多了就熟了...昨天看了书,今天调试的时候敲了好多遍,感觉满脑子是tree+heap.

p.s.

1.rank,kth,pre,suc函数都可以写成非递归的形式.

2.remove函数有两种写法:

(1).LRJ白书上的方法:

  如果待删除节点只有一个子树,则用该子树代替待删除节点,删除待删除节点即可.如果有两个子树,则将优先值小的(小根堆)子树旋转上去,再在另一  个子树中递归删除待删除节点,每次这样的旋转操作都会减小子树,最终会达到第一种情况.

(2).在题解里看来的方法:

  如果待删除节点没有子树,那么可以直接删除.如果有子树,则不管有两个还是一个,将优先值小的子树旋转上去(这里注意可以将null的优先值设为   INF),然后再在另一个子树中递归删除节点,每次这样的旋转操作都会减小子树,最终会达到第一种情况.

 

#include <cstdio>
#include <cstdlib>
using namespace std;

const int oo=~0u<<1;

struct Treap{
    struct node{
        node* ch[2];
        int v,s,r,c;
        node(int v,node *t):v(v){ ch[0]=ch[1]=t; r=rand(); s=c=1; }
        bool operator < (const node &rhs) const { return r<rhs.r; }
        void push_up(){ s=ch[0]->s+ch[1]->s+c; }
    }*root,*null;
    Treap(){
        null=new node(0,0);
        null->s=null->c=0;
        null->r=oo;
        root=null;
    }
    void rotate(node* &o,bool d){
        node* k=o->ch[!d]; o->ch[!d]=k->ch[d]; k->ch[d]=o;
        o->push_up(); k->push_up(); o=k;
    }
    void insert(node* &o,int x){
        if(o==null) o=new node(x,null);
        else{
            if(o->v==x){
                o->c++; o->s++;
            }
            else{
                bool d=x>o->v;
                insert(o->ch[d],x);
                if(o->ch[d]<o) rotate(o,!d);
                o->push_up();
            }
        }
    }
    void remove(node* &o,int x){
        if(o->v==x){
            if(o->c>1) o->c--;
            else{
                if(o->ch[0]!=null&&o->ch[1]!=null){
                    bool d=o->ch[0]<o->ch[1];
                    rotate(o,d); remove(o->ch[d],x);
                }
                else{
                    node* u=o;
                    if(o->ch[0]==null) o=o->ch[1];
                    else o=o->ch[0];
                    delete u;
                }
            }
        }
        else{
            bool d=x>o->v;
            remove(o->ch[d],x);
        }
        if(o!=null) o->push_up();
    }
    int kth(node* o,int k){
        int s=o->ch[0]->s+o->c;
        if(k>o->ch[0]->s&&k<=s) return o->v;
        if(k<=o->ch[0]->s) return kth(o->ch[0],k);
        else return kth(o->ch[1],k-s);
    }
    int rank(node *o,int x){
        int s=o->ch[0]->s+o->c;
        if(x==o->v) return o->ch[0]->s+1;
        if(x<o->v) return rank(o->ch[0],x);
        else return s+rank(o->ch[1],x);
    }
    int pre(int x){
        node* t=root;
        int ret=0;
        while(t!=null){
            if(t->v<x){
                ret=t->v;
                t=t->ch[1];
            }
            else t=t->ch[0];
        }
        return ret;
    }
    int suc(int x){
        node *t=root;
        int ret=0;
        while(t!=null){
            if(t->v>x){
                ret=t->v;
                t=t->ch[0];
            }
            else t=t->ch[1];
        }
        return ret;
    }
}tree;

int main()
{
    int n,a,b;
    scanf("%d",&n);
    while(n--){
        scanf("%d%d",&a,&b);
        switch(a){
            case(1):tree.insert(tree.root,b);break;
            case(2):tree.remove(tree.root,b);break;
            case(3):printf("%d\n",tree.rank(tree.root,b));break;
            case(4):printf("%d\n",tree.kth(tree.root,b));break;
            case(5):printf("%d\n",tree.pre(b));break;
            case(6):printf("%d\n",tree.suc(b));break;
        }
    }
    return 0;
}

 

BZOJ_3224_普通平衡树(Treap)

标签:

原文地址:http://www.cnblogs.com/Sunnie69/p/5483880.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!