BZOJ 3224: Tyvj 1728 普通平衡树

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

10

1 106465

4 1

1 317721

1 460929

1 644985

1 84185

1 89851

6 81968

1 492737

5 493598

Sample Output

106465

84185

492737

HINT

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

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

分析

就是学splay模板而已,但我感觉常数好大,之后慢慢改改

代码

#include <bits/stdc++.h>

#define N 500000

struct
{
    int fa;
    int son[3];
    int size[3];
    int count;
    int cover;
}t[N];

int n;
int node;
int root;

void rotate(int x,int w)
{
    int f = t[x].fa;
    int g = t[f].fa;
    t[f].son[3 - w] = t[x].son[w];
    if (t[x].son[w])
        t[t[x].son[w]].fa = f;
    t[x].fa = g;
    t[f].size[3 - w] = t[x].size[w];
    t[x].size[w] += t[f].size[w] + 1;
    if (g)
    {
        if (f == t[g].son[1])
            t[g].son[1] = x;
        else t[g].son[2] = x;
    }
    t[f].fa = x;
    t[x].son[w] = f;
}

void splay(int x)
{
    int y;
    while (t[x].fa)
    {
        y = t[x].fa;
        if (!t[y].fa)
        {
            if (x == t[y].son[1])
                rotate(x,2);
            else rotate(x,1);
            continue;
        }
        if (y == t[t[y].fa].son[1])
        {
            if (x == t[y].son[1])
                rotate(y,2), rotate(x,2);
            else rotate(x,1), rotate(x,2);
        }
        else
        {
            if (x == t[y].son[2])
                rotate(y,1), rotate(x,1);
            else rotate(x,2), rotate(x,1);
        }
    }
    root = x;
}

void insert(int x,int add)
{
    if (t[x].cover >= add)
    {
        if (!t[x].son[1])
        {
            t[x].son[1] = ++node;
            t[node].cover = add;
            t[node].fa = x;
            if (!root)
                root = node;
        }
        else insert(t[x].son[1],add);
        t[x].size[1]++;
    }
    else
    {
        if (!t[x].son[2])
        {
            t[x].son[2] = ++node;
            t[node].cover = add;
            t[node].fa = x;
            if (!root)
                root = node;
        }
        else insert(t[x].son[2],add);
        t[x].size[2]++;
    }
}

void del(int x,int dec)
{
    if (!x)
        return;
    if (dec == t[x].cover)
    {
        splay(x);

        if (!t[x].son[1] && !t[x].son[2])
        {
            root = 0;
            return;
        }

        if (!t[x].son[1])
        {
            root = t[x].son[2];
            t[t[x].son[2]].fa = 0;
            return;
        }

        if (!t[x].son[2])
        {
            root = t[x].son[1];
            t[t[x].son[1]].fa = 0;
            return;
        }

        int f = t[x].son[1];
        int tmp = t[x].son[2];
        while (t[f].son[2])
            f = t[f].son[2];
        splay(f);
        t[f].son[2] = tmp;
        t[tmp].fa = f;
        return;
    }
    if (dec < t[x].cover)
        del(t[x].son[1],dec);
    else del(t[x].son[2],dec);
}

int kth(int x,int add,int now)
{
    insert(root,add);
    splay(node);
    int ans = t[node].size[1] + 1;
    del(node,add);
    return ans;
}

int findK(int x,int k)
{
    if (k == t[x].size[1] + 1)
        return t[x].cover;
    if (k <= t[x].size[1])
        return findK(t[x].son[1],k);
    else return findK(t[x].son[2],k - t[x].size[1] - 1);
}

bool flag;

int pred(int x,int k)
{
    int f = t[x].son[1];
    if (!f)
        return 0;
    while (t[f].son[2])
        f = t[f].son[2];
    if (t[f].cover != k)
        flag = 1;
    return f;
}

int succ(int x,int k)
{
    int f = t[x].son[2];
    if (!f)
        return 0;
    while (t[f].son[1])
        f = t[f].son[1];
    if (t[f].cover != k)
        flag = 1;
    return f;
}

int main()
{
    int n;
    scanf("%d",&n);
    for (int i = 1; i <= n; i++)
    {
        int opt,x;
        scanf("%d%d",&opt,&x);
        if (opt == 1)
            insert(root,x), splay(node);
        if (opt == 2)
            del(root,x);
        if (opt == 3)
            printf("%d\n",kth(root,x,0));
        if (opt == 4)
            printf("%d\n",findK(root,x));
        if (opt == 5)
        {
            int ans;
            insert(root,x);
            splay(node);
            for (flag = 0, ans = pred(root,x); !flag || !ans; splay(ans), ans = pred(root,x));
            del(root,x);
            printf("%d\n",t[ans].cover);
        }
        if (opt == 6)
        {
            int ans;
            insert(root,x);
            splay(node);
            for (flag = 0, ans = succ(root,x); !flag || !ans; splay(ans), ans = succ(root,x));
            del(root,x);
            printf("%d\n",t[ans].cover);
        }
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值