bzoj3224 Tyvj 1728 普通平衡树

3224: Tyvj 1728 普通平衡树

Time Limit: 10 Sec  Memory Limit: 128 MB
Submit: 18119  Solved: 7981
[Submit][Status][Discuss]

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]

 

Source

分析:splay模板题,只是需要注意可能有多个相同的数,需要记录值为x的数有多少个.
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>

using namespace std;

const int maxn = 200010;
int n,m,sizee[maxn],pos[maxn],tot,root,a[maxn];

struct node
{
    int fa,left,right,v,cnt;
}e[maxn];

void update(int x)
{
    sizee[x] = e[x].cnt;
    if (e[x].left != -1)
        sizee[x] += sizee[e[x].left];
    if (e[x].right != -1)
        sizee[x] += sizee[e[x].right];
}

int getsize(int x)
{
    if (x == -1)
        return 0;
    return sizee[x];
}

void turnr(int x)
{
    int y = e[x].fa;
    int z = e[y].fa;
    e[y].left = e[x].right;
    if (e[x].right != -1)
        e[e[x].right].fa = y;
    e[x].fa = z;
    if (z != -1)
    {
        if (e[z].left == y)
            e[z].left = x;
        else
            e[z].right = x;
    }
    e[x].right = y;
    e[y].fa = x;
    update(y);
    update(x);
}

void turnl(int x)
{
    int y = e[x].fa;
    int z = e[y].fa;
    e[y].right = e[x].left;
    if (e[x].left != -1)
        e[e[x].left].fa = y;
    e[x].fa = z;
    if (z != -1)
    {
        if (e[z].left == y)
            e[z].left = x;
        else
            e[z].right = x;
    }
    e[x].left = y;
    e[y].fa = x;
    update(y);
    update(x);
}

void splay(int x)
{
    while (e[x].fa != -1)
    {
        int y = e[x].fa;
        int z = e[y].fa;
        if (z == -1)
        {
            if (x == e[y].left)
                turnr(x);
            else
                turnl(x);
        }
        else
        {
            if (e[z].left == y && e[y].left == x)
            {
                turnr(y);
                turnr(x);
            }
            else
            {
                if (e[z].right == y && e[y].right == x)
                {
                    turnl(y);
                    turnl(x);
                }
                else
                {
                    if (e[z].left == y && e[y].right == x)
                    {
                        turnl(x);
                        turnr(x);
                    }
                    else
                    {
                            turnr(x);
                            turnl(x);
                    }
                }
            }
        }
    }
    root = x;
}

int find(int x)
{
    int p = root;
    while (p != -1)
    {
        if (e[p].v == x)
            return p;
        if (x < e[p].v)
            p = e[p].left;
        else
            p = e[p].right;
    }
    return p;
}

void del(int x)
{
    int p = find(x);
    splay(p);
    if (e[p].cnt > 1)
        {
            e[p].cnt--;
            update(p);
            return;
        }
    if (e[p].left == -1 && e[p].right == -1)
    {
        root = -1;
        return;
    }
    if (e[p].left == -1)
    {
        root = e[p].right;
        e[e[p].right].fa = -1;
        return;
    }
    if (e[p].right == -1)
    {
        root = e[p].left;
        e[e[p].left].fa = -1;
        return;
    }
    int j = e[p].left;
    while (e[j].right != -1)
        j = e[j].right;
    splay(j);
    e[j].right = e[p].right;
    e[e[p].right].fa = j;
    update(j);
}

void insert(int x,int y)
{
    if (e[y].v == x)
    {
        e[y].cnt++;
        splay(y);
        update(y);
        return;
    }
    if (x < e[y].v)
    {
        if (e[y].left == -1)
        {
            e[y].left = ++tot;
            e[tot].left = e[tot].right = -1;
            e[tot].v = x;
            e[tot].fa = y;
            e[tot].cnt = 1;
            sizee[tot] = 1;
            return;
        }
        else
            insert(x,e[y].left);
    }
    else
    {
        if (e[y].right == -1)
        {
            e[y].right = ++tot;
            e[tot].left = e[tot].right = -1;
            e[tot].v = x;
            e[tot].fa = y;
            e[tot].cnt = 1;
            sizee[tot] = 1;
            return;
        }
        insert(x,e[y].right);
    }
    update(y);
}

int query(int x)
{
    int p = root,res = 0;
    while (p != -1)
    {
        if (x < e[p].v)
            p = e[p].left;
        else
        {
            res += getsize(e[p].left);
            if (x == e[p].v)
                return res + 1;
            res += e[p].cnt;
            p = e[p].right;
        }
    }
    return res;
}

int query2(int x)
{
    int p = root;
    while (p != -1)
    {
        if (e[p].left && x <= sizee[e[p].left])
        p = e[p].left;
        else
        {
            int temp = getsize(e[p].left) + e[p].cnt;
            if (x <= temp)
            return e[p].v;
            x -= temp;
            p = e[p].right;
        }
    }
    return p;
}

int findl(int x)
{
    int p = root,maxx = 0x7fffffff,cur = x;
    while (p != -1)
    {
        if (e[p].v < x && x - e[p].v < maxx)
        {
            maxx = x - e[p].v;
            cur = e[p].v;
        }
        if (x <= e[p].v)
            p = e[p].left;
        else
            p = e[p].right;
    }
    return cur;
}

int findr(int x)
{
    int p = root,maxx = 0x7fffffff,cur = x;
    while (p != -1)
    {
        if(e[p].v > x && e[p].v - x < maxx)
        {
            maxx = e[p].v - x;
            cur = e[p].v;
        }
        if (x >= e[p].v)
            p = e[p].right;
        else
            p = e[p].left;
    }
    return cur;
}

int main()
{
    scanf("%d",&n);
    root = -1;
    for (int i = 1; i <= n; i++)
    {
        int opt,x;
        scanf("%d%d",&opt,&x);
        if (opt == 1)
        {
            if (root == -1)
            {
                root = ++tot;
                e[tot].left = e[tot].right = e[tot].fa = -1;
                e[tot].cnt = 1;
                e[tot].v = x;
                sizee[tot] = 1;
            }
            else
                insert(x,root);
            splay(tot);
            update(tot);
        }
        if (opt == 2)
            del(x);
        if (opt == 3)
            printf("%d\n",query(x));
        if (opt == 4)
            printf("%d\n",query2(x));
        if (opt == 5)
            printf("%d\n",findl(x));
        if (opt == 6)
            printf("%d\n",findr(x));
    }

    return 0;
}

 

posted @ 2018-01-10 23:16  zbtrs  阅读(158)  评论(0编辑  收藏  举报