普通平衡树

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

#include<bits/stdc++.h>
#define int long long int
#define INF 0x7f7f7f7f
 
using namespace std;
 
struct node
{
    int ls, rs;
    int key, pri;
    int cnt, size;
} tree[100001];
int root, n, idx;
 
void pushup( int p )
{
    tree[p].size = tree[tree[p].ls].size + tree[tree[p].rs].size + tree[p].cnt;
}
 
void rightrotate( int &p )
{
    int q = tree[p].ls;
    tree[p].ls = tree[q].rs;
    tree[q].rs = p;
    p = q;
    pushup(tree[p].rs);
}
 
void leftrotate( int &p )
{
    int q = tree[p].rs;
    tree[p].rs = tree[q].ls;
    tree[q].ls = p;
    p = q;
    pushup(tree[p].ls);
}
 
int getnode( int key )
{
    tree[++idx].key = key;
    tree[idx].pri = rand();
    tree[idx].cnt = tree[idx].size = 1;
    return idx; 
}
 
void insert( int &p, int key )
{
    if( p == 0 )
    {
        p = getnode(key);
        return;
    }
    else if( tree[p].key > key )
    {
        insert( tree[p].ls, key );
         
        if( tree[tree[p].ls].pri > tree[p].pri )
        {
            rightrotate( p );
        }
    }
    else if( tree[p].key == key )
    {
        tree[p].cnt++;
    }
    else
    {
        insert( tree[p].rs, key );
         
        if( tree[tree[p].rs].pri > tree[p].pri )
        {
            leftrotate( p );
        }
    }
     
    pushup(p);
}
 
void remove( int &p, int key )
{
    if( p == 0 )
    {
        return ;
    }
     
    if( tree[p].key > key )
    {
        remove( tree[p].ls, key );
    }
    else if( tree[p].key < key )
    {
        remove( tree[p].rs, key );
    }
    else if( tree[p].cnt > 1 )
    {
        tree[p].cnt--;
    }
    else
    {
    	if( tree[p].rs == 0 && tree[p].ls != 0 )
    	{
            rightrotate(p);
            remove( tree[p].rs, key );
		}
    	else if( tree[p].ls == 0 && tree[p].rs != 0 )
    	{
            leftrotate(p);
            remove( tree[p].ls, key );
		}
		else if( tree[tree[p].ls].pri > tree[tree[p].rs].pri )
		{
            rightrotate(p);
            remove( tree[p].rs, key );
		}
		else if( tree[p].ls == 0 && tree[p].rs == 0 )
		{
			p = 0;
		}
		else
		{
            leftrotate(p);
            remove( tree[p].ls, key );
		}
    }
     
    pushup(p);
}
 
int getrank( int p, int key )
{
    if( p == 0 )
    {
        return 1;
    }
     
    if( tree[p].key > key )
    {
        return getrank( tree[p].ls, key );
    }
    else if( tree[p].key < key )
    {
        return tree[tree[p].ls].size + tree[p].cnt + getrank( tree[p].rs, key );
    }
    else
    {
        return tree[tree[p].ls].size + 1;
    }
}
 
int getkey( int p, int rank )
{
    if( p == 0 )
    {
        return INF;
    }
     
    if( tree[tree[p].ls].size >= rank )
    {
        return getkey( tree[p].ls, rank );
    }
    else if( rank > tree[tree[p].ls].size + tree[p].cnt )
    {
        return getkey( tree[p].rs, rank - tree[tree[p].ls].size - tree[p].cnt );
    }
    else
    {
        return tree[p].key;
    }
}
 
int getprev( int p, int key )
{
    if( p == 0 )
    {
        return -INF;
    }
     
    if( tree[p].key >= key )
    {
        return getprev( tree[p].ls, key );
    }
    else
    {
        return max( tree[p].key, getprev( tree[p].rs, key ) );
    }
}
 
int getnext( int p, int key )
{
    if( p == 0 )
    {
        return INF;
    }
     
    if( tree[p].key <= key )
    {
        return getnext( tree[p].rs, key );
    }
     
    return min( tree[p].key, getnext( tree[p].ls, key ) );
}
 
signed main()
{
    cin >> n;
     
    for( int i = 1; i <= n; i++ )
    {
        int opt, x;
         
        cin >> opt >> x;
         
        if( opt == 1 )
        {
            insert( root, x );
        }
        else if( opt == 2 )
        {
            remove( root, x );
        }
        else if( opt == 3 )
        {
            cout << getrank( root, x ) << endl;
        }
        else if( opt == 4 )
        {
            cout << getkey( root, x ) << endl;
        }
        else if( opt == 5 )
        {
            cout << getprev( root, x ) << endl;
        }
        else if( opt == 6 )
        {
            cout << getnext( root, x ) << endl;
        }
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值