您的位置:首页 > 其它

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

2015-12-03 20:30 453 查看

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

[code]10

1 106465

4 1

1 317721

1 460929

1 644985

1 84185

1 89851

6 81968

1 492737

5 493598


Sample Output

[code]106465

84185

492737


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节点转到父节点的位置上。

附上代码:

[code]#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; 
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: