【模板】【bzoj3224】Tyvj 1728 普通平衡树 Splay

来源:互联网 发布:arduino 单片机 编辑:程序博客网 时间:2024/05/20 05:10

Description

您需要写一种数据结构(可参考题目标题),来维护一些数,其中需要提供以下操作:
1. 插入x数
2. 删除x数(若有多个相同的数,因只删除一个)
3. 查询x数的排名(若有多个相同的数,因输出最小的排名)
4. 查询排名为x的数
5. 求x的前驱(前驱定义为小于x,且最大的数)
6. 求x的后继(后继定义为大于x,且最小的数)

Input

第一行为n,表示操作的个数,下面n行每行有两个数opt和x,opt表示操作的序号(1<=opt<=6)

Output

对于操作3,4,5,6每行输出一个数,表示对应答案

Sample Input

101 1064654 11 3177211 4609291 6449851 841851 898516 819681 4927375 493598

Sample Output

10646584185492737

HINT

1.n的数据范围:n<=100000

2.每个数的数据范围:[-1e7,1e7]

Source

平衡树


终于把splay艹出来了!!!!!!!!!!!!!

不过还是抄的viv&&小绿的模板 _(: 3

自己悟的splay总是RE之类的……没看书就用指针就是我这种下场……得抽空补一下语言
基础了…………

说一下基本操作:
插入:按普通平衡树那样插入,插入完了splay到根。
删除:splay到根,如果只有一个儿子,则改一下根的指针到那个儿子即可。若有俩儿子,则把这个数的前驱splay到根的左儿子位置上,然后改一下根的指针指向前驱即可。
剩余四个操作看代码就懂了…

splay(p,rt) :把p节点转到父节点为rt的位置上。
rotate(p):把p节点转到父节点的位置上。

附上代码:

#include <cstdio>#include <iostream>#include <cstring>#include <algorithm>using namespace std;const int SZ = 1000010;const int INF = 1000000010;struct node{    node *ch[2],*f;    int sz,cnt,v;    void maintain()    {        sz = cnt + ch[0] -> sz + ch[1] -> sz;     }    int cmp(int x)    {        if(x == v) return -1;        return x < v ? 0 : 1;     }    int dir()    {        return f -> ch[1] == this;    }    void setc(node *x,int d)    {        (ch[d] = x) -> f = this;    }}T[SZ], *root, *null;int Tcnt = 0;node* newnode(int x,node *f){    node *k = T + (++ Tcnt);    k -> v = x;    k -> ch[0] = k -> ch[1] = null;    k -> sz = k -> cnt = 1;    k -> f = f;    return k;}void rotate(node *p){    node *fa = p -> f;    int d = p -> dir();    fa -> f -> setc(p,fa -> dir());    fa -> setc(p -> ch[d ^ 1],d); fa -> maintain();    p -> setc(fa,d ^ 1); p -> maintain();    if(fa == root) root = p;}void splay(node *p,node *rt = null){    while(p -> f != rt)    {        if(p -> f -> f == rt) rotate(p);        else         {            if(p -> dir() == p -> f -> dir())                rotate(p -> f),rotate(p);            else                rotate(p),rotate(p);        }    }}void insert(node *p,int x){    if(root == null) { root = newnode(x,null); return ; }    while(p != null)    {        p -> sz ++;        int d = p -> cmp(x);        if(d == -1) { p -> cnt ++; break; }        if(p -> ch[d] == null)        {            p -> ch[d] = newnode(x,p);            p = p -> ch[d];            break;        }        p = p -> ch[d];     }    splay(p);}void erase(node *p,int x){    while(p != null)    {        p -> sz --;        int d = p -> cmp(x);        if(d == -1) { p -> cnt --; break; }        p = p -> ch[d];     }    if(p -> cnt) return ;    splay(p);    if(p -> ch[0] == null) { root = p -> ch[1]; root -> f = null; return ; }    if(p -> ch[1] == null) { root = p -> ch[0]; root -> f = null; return ; }    p = p -> ch[0];    while(p -> ch[1] != null) p = p -> ch[1];    splay(p,root);    p -> ch[1] = root -> ch[1]; p -> ch[1] -> f = p;    p -> f = null; p -> maintain();    root = p;}int ask_rank(node *p,int x){    int ans = 0;    while(p != null)    {        int d = p -> cmp(x);        if(d == -1) return ans + p -> ch[0] -> sz + 1;        if(d == 1) ans += p -> ch[0] -> sz + p -> cnt;        p = p -> ch[d];    }    return -1;}int ask_num(node *p,int k){    while(p != null)    {        int l = p -> ch[0] -> sz + 1;        int r = p -> ch[0] -> sz + p -> cnt;        if(l <= k && k <= r) return p -> v;        if(k > r) k -= r,p = p -> ch[1];        else p = p -> ch[0];    }}int ask_pre(node *p,int x){    int ans = 0;    while(p != null)    {        if(p -> v < x)            ans = p -> v,p = p -> ch[1];        else             p = p -> ch[0];    }    return ans;}int ask_suf(node *p,int x){    int ans = 0;    while(p != null)    {        if(p -> v > x)            ans = p -> v,p = p -> ch[0];        else             p = p -> ch[1];    }    return ans;}void init(){    null = newnode(-INF,null);    null -> sz = null -> cnt = 0;    root = null;}int main(){    init();    int n;    scanf("%d",&n);    while(n --)    {        int opt,x;        scanf("%d%d",&opt,&x);        switch(opt)        {            case 1:                insert(root,x);                break;            case 2:                erase(root,x);                break;            case 3:                printf("%d\n",ask_rank(root,x));                break;            case 4:                printf("%d\n",ask_num(root,x));                break;            case 5:                printf("%d\n",ask_pre(root,x));                break;             case 6:                                 printf("%d\n",ask_suf(root,x));                break;        }    }    return 0; }
0 0
原创粉丝点击