2013-team4/code/treap

从 Trac 迁移的文章

这是从旧校内 Wiki 迁移的文章,可能存在一些样式问题,您可以向 memset0 反馈。

原文章内容如下:

{{{
Treap 不释放内存,可以有重复数据
DATA 为数据类型
}}}
{{{
创建
Treap tree;
清空
tree.clear();
插入
tree.insert(x);
删除
tree.erase(x);
第 k 小元素,k 从 0 开始到 size - 1
tree[k];
计数
tree.count(x);
上下界,返回 int 下标
tree.lower_bound();
tree.upper_bound();
}}}
{{{
typedef int DATA;
struct Node{
    Node *ch[2];
    int rank, size, cnt;
    DATA v;
    Node(DATA val){
        ch[0] = ch[1] = NULL;
        rank = rand();
        size = 1;
        cnt = 1;
        v = val;    
    }
    int cmp(DATA x) const{
        if(x == v) return -1;
        return x < v ? 0 : 1;
    }
    void update(){
        size = cnt;
        if(ch[0] != NULL) size += ch[0]->size;
        if(ch[1] != NULL) size += ch[1]->size;
    }
};
struct Treap{
    Node *rt;    
    Treap(){
        clear();
    }
    void clear(){
        rt = NULL;
    }
    void rotate(Node *&o, int d){
        Node *k = o->ch[d ^ 1];
        o->ch[d ^ 1] = k->ch[d];
        k->ch[d] = o;
        o->update(); 
        k->update();
        o = k;
    }
    void insert(Node *&o, DATA x){
        if(o == NULL) o = new Node(x);
        else{
            int d = o->cmp(x);
            if(d == -1) o->cnt++;
            else{
                insert(o->ch[d], x);
                if(o->rank < o->ch[d]->rank) rotate(o, d ^ 1);
            }
        }
        o->update();
    }
    void insert(DATA x){
        insert(rt, x);
    }
    void erase(Node *&o, DATA x){
        if(o == NULL) return;
        int d = o->cmp(x);
        if(d == -1){
            if(o->cnt > 1) o->cnt--;
            else{
                if(o->ch[0] == NULL) o = o->ch[1];
                else if(o->ch[1] == NULL) o = o->ch[0];
                else{
                    int d2 = (o->ch[0]->rank > o->ch[1]->rank ? 1 : 0);
                    rotate(o, d2);
                    erase(o->ch[d2], x);
                }
            }
        }
        else erase(o->ch[d], x);
        if(o != NULL) o->update();
    }
    void erase(DATA x){
        erase(rt, x);
    }
    int count(DATA x){
        for(Node *o = rt; true; ){
            if(o == NULL) return 0;
            int d = o->cmp(x);
            if(d == -1) return o->cnt;
            o = o->ch[d];
        }
    }
    int lower_bound(DATA x){
        int ret = 0, d;
        for(Node *o = rt; true; o = o->ch[d]){
            if(o == NULL) return ret;
            d = o->cmp(x);
            if(d != 0 && o->ch[0] != NULL) ret += o->ch[0]->size;
            if(d == -1) return ret;
            if(d == 1) ret += o->cnt;
        }
    }
    int upper_bound(DATA x){
        int ret = 0, d;
        for(Node *o = rt; true; o = o->ch[d]){
            if(o == NULL) return ret;
            d = o->cmp(x);
            if(d != 0 && o->ch[0] != NULL) ret += o->ch[0]->size;
            if(d == -1) return ret + o->cnt;
            if(d == 1) ret += o->cnt;
        }
    }
    DATA operator[](int k) const{
        if(k >= rt->size || k < 0) abort();
        for(Node *o = rt; true; ){
            int sl = (o->ch[0] == NULL ? 0 : o->ch[0]->size);
            if(k < sl) o = o->ch[0];
            else{
                k -= sl;
                if(k < o->cnt) return o->v;
                k -= o->cnt;
                o = o->ch[1];
            }
        }
    }
    int size() const{
        return rt->size;
    }
};
}}}
Treap 不释放内存,可以有重复数据
DATA 为数据类型
创建
Treap tree;
清空
tree.clear();
插入
tree.insert(x);
删除
tree.erase(x);
第 k 小元素,k 从 0 开始到 size - 1
tree[k];
计数
tree.count(x);
上下界,返回 int 下标
tree.lower_bound();
tree.upper_bound();
typedef int DATA;
struct Node{
    Node *ch[2];
    int rank, size, cnt;
    DATA v;
    Node(DATA val){
        ch[0] = ch[1] = NULL;
        rank = rand();
        size = 1;
        cnt = 1;
        v = val;    
    }
    int cmp(DATA x) const{
        if(x == v) return -1;
        return x < v ? 0 : 1;
    }
    void update(){
        size = cnt;
        if(ch[0] != NULL) size += ch[0]->size;
        if(ch[1] != NULL) size += ch[1]->size;
    }
};
struct Treap{
    Node *rt;    
    Treap(){
        clear();
    }
    void clear(){
        rt = NULL;
    }
    void rotate(Node *&o, int d){
        Node *k = o->ch[d ^ 1];
        o->ch[d ^ 1] = k->ch[d];
        k->ch[d] = o;
        o->update(); 
        k->update();
        o = k;
    }
    void insert(Node *&o, DATA x){
        if(o == NULL) o = new Node(x);
        else{
            int d = o->cmp(x);
            if(d == -1) o->cnt++;
            else{
                insert(o->ch[d], x);
                if(o->rank < o->ch[d]->rank) rotate(o, d ^ 1);
            }
        }
        o->update();
    }
    void insert(DATA x){
        insert(rt, x);
    }
    void erase(Node *&o, DATA x){
        if(o == NULL) return;
        int d = o->cmp(x);
        if(d == -1){
            if(o->cnt > 1) o->cnt--;
            else{
                if(o->ch[0] == NULL) o = o->ch[1];
                else if(o->ch[1] == NULL) o = o->ch[0];
                else{
                    int d2 = (o->ch[0]->rank > o->ch[1]->rank ? 1 : 0);
                    rotate(o, d2);
                    erase(o->ch[d2], x);
                }
            }
        }
        else erase(o->ch[d], x);
        if(o != NULL) o->update();
    }
    void erase(DATA x){
        erase(rt, x);
    }
    int count(DATA x){
        for(Node *o = rt; true; ){
            if(o == NULL) return 0;
            int d = o->cmp(x);
            if(d == -1) return o->cnt;
            o = o->ch[d];
        }
    }
    int lower_bound(DATA x){
        int ret = 0, d;
        for(Node *o = rt; true; o = o->ch[d]){
            if(o == NULL) return ret;
            d = o->cmp(x);
            if(d != 0 && o->ch[0] != NULL) ret += o->ch[0]->size;
            if(d == -1) return ret;
            if(d == 1) ret += o->cnt;
        }
    }
    int upper_bound(DATA x){
        int ret = 0, d;
        for(Node *o = rt; true; o = o->ch[d]){
            if(o == NULL) return ret;
            d = o->cmp(x);
            if(d != 0 && o->ch[0] != NULL) ret += o->ch[0]->size;
            if(d == -1) return ret + o->cnt;
            if(d == 1) ret += o->cnt;
        }
    }
    DATA operator[](int k) const{
        if(k >= rt->size || k < 0) abort();
        for(Node *o = rt; true; ){
            int sl = (o->ch[0] == NULL ? 0 : o->ch[0]->size);
            if(k < sl) o = o->ch[0];
            else{
                k -= sl;
                if(k < o->cnt) return o->v;
                k -= o->cnt;
                o = o->ch[1];
            }
        }
    }
    int size() const{
        return rt->size;
    }
};