【树】【平衡树】Splay自顶向下模板

操作1插入x
操作2删除x
操作3查询x排名
操作4查询排名为x的数
操作5查询x的前驱
操作6查询x的后继

#include <cstdio>
#include <cstring>
#include <iostream>
using namespace std;
struct node{
    int sz, val;
    node *ch[2];
    node(){ch[0] = ch[1] = this; val = sz = 0;}
    node *resize(){return sz=ch[0]->sz+ch[1]->sz+1, this;}
}Tnull, *nil=&Tnull, *root;
node *newnode(node *lch, node *rch, int v){
    node *ret = new node;
    ret->val = v;
    ret->ch[0] = lch, ret->ch[1] = rch;
    return ret;
}
void build(){root = (newnode(nil, nil, 100000000))->resize();}
void Zig(bool d){
    node *tmp = root->ch[d];
    root->ch[d] = nil->ch[d];
    nil->ch[d] = root;
    root = tmp;
}
void ZigZig(bool d){
    node *tmp = root->ch[d]->ch[d];
    root->ch[d]->ch[d] = nil->ch[d];
    nil->ch[d] = root->ch[d];
    root->ch[d] = nil->ch[d]->ch[!d];
    nil->ch[d]->ch[!d] = root->resize();
    root = tmp;
}
void Finish(bool d){
    node *p=root->ch[!d], *t=nil->ch[d];
    while(t != nil){
        t = nil->ch[d]->ch[d];
        nil->ch[d]->ch[d] = p;
        p = nil->ch[d]->resize();
        nil->ch[d] = t;
    }
    root->ch[!d] = p;
}
void Select(int u){
    bool d, dd; int t;
    while(true){
        d = (t = root->ch[0]->sz) < u;
        if(t == u || root->ch[d] == nil) break;
        if(d) u -= t + 1;
        dd = (t = root->ch[d]->ch[0]->sz) < u;
        if(t == u || root->ch[d]->ch[dd] == nil){Zig(d);break;}
        if(dd) u -= t + 1;
        if(d == dd) ZigZig(dd);
        else Zig(d), Zig(dd);
    }
    Finish(0); Finish(1);
    root->resize();
}
void Search(int u){
    bool d, dd;
    while(true){
        d = root->val < u;
        if(root->ch[d] == nil) break;
        dd = root->ch[d]->val < u;
        if(root->ch[d]->ch[dd] == nil){Zig(d); break;}
        if(d == dd) ZigZig(dd);
        else Zig(d), Zig(dd);
    }
    Finish(0); Finish(1);
    root->resize();
    if(root->val < u) Select(root->ch[0]->sz+1);
}
void Insert(int v){
    Search(v);
    node *newroot = newnode(root->ch[0], root, v);
    root->ch[0] = nil;
    root->resize();
    root = newroot->resize();
}
void Delete(int v){
    Search(v);
    if(root->val != v) return ;
    node *oldroot = root;
    root = oldroot->ch[1];
    Select(0);
    root->ch[0] = oldroot->ch[0];
    root->resize();
    delete oldroot;
}
int XRank(int x){
    Select(x-1);
    return root->val;
}
int FRank(int x){
    Search(x);
    return root->ch[0]->sz+1;
}
int Pre(int x){
    Search(x);
    Select(root->ch[0]->sz-1);
    return root->val;
}
int Bak(int x){
    Search(x);
    if(root->val != x)
        return root->val;
    Search(x+1);
    return root->val;
}
int main(){
    build();
    int n, ord, x;
    scanf("%d", &n);
    for(int i=1;i<=n;i++){
        scanf("%d%d", &ord, &x);
        switch(ord){
            case 1: Insert(x);
                break;
            case 2: Delete(x);
                break;
            case 3: printf("%d\n", FRank(x));
                break;
            case 4: printf("%d\n", XRank(x));
                break;
            case 5: printf("%d\n", Pre(x));
                break;
            case 6: printf("%d\n", Bak(x));
                break;
        }
    }

    return 0;
}

posted on 2016-03-10 13:49  JeremyGuo  阅读(195)  评论(0编辑  收藏  举报

导航