【bzoj3224】普通平衡树

到现在才想起来我还不会写splay……
QAQ
在DQS学长写模板的时候带了我下……
QAQ人生第一个维护数的splay
QAQQQQQQQ

要记得在del、rot、newnode这种设计更新根的操作的时候一定要root = x;root -> f = null

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
using namespace std;
const int MAXN = 100000 + 5;
struct tr
{
    tr *ch[2],*f;
    int v,sz,cnt;
    bool dir()
    {
        return f -> ch[1] == this;
    }
    void maintain()
    {
        sz = cnt + ch[0] -> sz + ch[1] -> sz;
        return;
    }
    void setc(tr *p,int d)
    {
        (ch[d] = p) -> f = this;
        return;
    }
}tree[MAXN],*root,*null;
int tot = 0;
tr* newnode(int x,tr* fa = null)
{
    tr *p = tree + (tot ++);
    p -> f = fa;
    p -> ch[0] = p -> ch[1] = null;
    p -> sz = p -> cnt = 1;
    p -> v = x;
    return p;
}
void reset()
{
    tot = 0;
    null = newnode(0);
    null -> sz = null -> cnt = 0;
    root = null;
    return;
}
void rot(tr *x)
{
    tr *p = x -> f;
    int d = x -> dir();
    p -> f -> setc(x,p -> dir());
    p -> setc(x -> ch[d ^ 1],d);
    p -> maintain();
    x -> setc(p,d ^ 1);
    x -> maintain();
    if(p == root)
        root = x;
    return;
}
void splay(tr* x,tr* to = null)
{
    while(x -> f != to)
    {
        if(x -> f -> f == to)
            rot(x);
        else
            x -> dir() == x -> f -> dir() ? (rot(x -> f),rot(x)) : (rot(x),rot(x));
    }
}
void insert(int x)
{
    if(root == null)
    {
        root = newnode(x);
        return;
    }
    tr* p = root;
    while(p != null)
    {
        p -> sz ++;
        if(p -> v == x)
        {
            p -> cnt++;
            break;
        }
        int d = x > p -> v;
        if(p -> ch[d] == null)
        {
            p -> ch[d] = newnode(x,p);
            p = p -> ch[d];
            break;
        }
        p = p -> ch[d];
    }
    splay(p);
    return;
}
tr* find(int x)
{
    tr* p = root;
    while(p != null)
    {
        if(p -> v == x)
            break;
        int d = x > p -> v;
        p = p -> ch[d];
    }
    splay(p);
    return p;
}
void del(int x)
{
    tr *p = find(x);
    splay(p);
    p -> sz --;
    if(--p -> cnt)
        return;
    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 -> setc(root -> ch[1],1);
    p -> f = null;
    p -> maintain();
    root = p;
    return;
}
int find_hj(int x)
{
    tr* p = root;
    int ans = 0;
    while(p != null)
    {
        if(x < p -> v)
            ans = p -> v,p = p -> ch[0];
        else
            p = p -> ch[1];
    }
    return ans;
}
int find_qq(int x)
{
    tr* p = root;
    int ans = 0;
    while(p != null)
    {
        if(x > p -> v)
            ans = p -> v,p = p -> ch[1];
        else
            p = p -> ch[0];
    }
    return ans;
}
int num_to_pm(int x)
{
    splay(find(x));
    return root -> ch[0] -> sz + 1;
}
int pm_to_num(int x)
{
    tr* p = root;
    while(p != null)
    {
        int l = p -> ch[0] -> sz + 1;
        int r = p -> ch[0] -> sz + p -> cnt;
        if(l <= x && x <= r)
            return p -> v;
        int d = x > p -> ch[0] -> sz + p -> cnt;
        if(d)
            x -= p -> ch[0] -> sz + p -> cnt;
        p = p -> ch[d];
    }
    return p -> v;
}

int n,q,x;
int main()
{
    reset();
    scanf("%d",&n);
    while(n --)
    {
        scanf("%d",&q);
        switch(q)
        {
            case 1:scanf("%d",&x);insert(x);break;
            case 2:scanf("%d",&x);del(x);break;
            case 3:scanf("%d",&x);printf("%d\n",num_to_pm(x));break;
            case 4:scanf("%d",&x);printf("%d\n",pm_to_num(x));break;
            case 5:scanf("%d",&x);printf("%d\n",find_qq(x));break;
            case 6:scanf("%d",&x);printf("%d\n",find_hj(x));break;
        }
    }
    return 0;
}
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值