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.每个数的数据范围:[-1e7,1e7]

Source

平衡树


明确告知你就是平衡树。

写一个treap就好


<pre name="code" class="cpp">#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdio>
#include<cstdlib>
#include<cmath>
using namespace std;
struct treap
{
    int l,r,v,size,rnd,w;
}t[100010];
int n,size,root,ans;
 
void update(int k);
void insert(int &k, int x);
void left_turn(int &k);
void right_turn(int &k);
int query_rank(int k, int x);
int query_num(int k, int x);
void query_pre(int k, int x);
void query_nst(int k, int x); 
void del(int &k, int x);
 
int main()
{
    scanf("%d",&n);
    for(int i = 1; i <= n; i ++)
    {
        int opt,x;
        scanf("%d%d",&opt,&x);
        switch(opt)
        {
            case 1: insert(root,x);break;
            case 2:  del(root,x);break;
            case 3: printf("%d\n",query_rank(root,x));break;
            case 4: printf("%d\n",query_num(root,x));break;
            case 5: ans = 0;query_pre(root,x);printf("%d\n",t[ans].v);break;
            case 6: ans = 0;query_nst(root,x);printf("%d\n",t[ans].v);break;
        }
    }
     
    return 0;
}
 
void update(int k)
{
    t[k].size = t[ t[k].l ].size + t[ t[k].r ].size + t[k].w;
}
 
void insert(int &k, int x)
{
    if(k == 0)
    {
        size ++;
        k = size;
        t[k].size = t[k].w = 1;
        t[k].v = x;
        t[k].rnd = rand();
        return;
    }
    t[k].size ++;
    if(t[k].v == x) t[k].w ++;
    else
        if(x > t[k].v)
        {
            insert(t[k].r,x);
            if(t[ t[k].r ].rnd < t[k].rnd) left_turn(k);
        }
        else
        {
            insert(t[k].l,x);
            if(t[ t[k].l ].rnd < t[k].rnd) right_turn(k);
        }
}
 
void right_turn(int &k)
{
    int p = t[k].l;
    t[k].l = t[p].r;
    t[p].r = k;
    t[p].size = t[k].size;
    update(k);
    k = p;
}
 
void left_turn(int &k)
{
    int p = t[k].r;
    t[k].r = t[p].l;
    t[p].l = k;
    t[p].size = t[k].size;
    update(k);
    k = p;
}
 
int query_rank(int k, int x)
{
    if(k == 0) return 0;
    if(t[k].v == x) return t[ t[k].l ].size + 1;
    else if(x > t[k].v) return t[ t[k].l ].size + t[k].w + query_rank(t[k].r,x);
    else return query_rank(t[k].l,x);
}
 
int query_num(int k, int x)
{
    if(k == 0) return 0;
    if(x <= t[ t[k].l ].size) return query_num(t[k].l,x);
    else if(x > t[ t[k].l ].size + t[k].w) return query_num(t[k].r,x - t[ t[k].l ].size - t[k].w);
    else return t[k].v;
}
 
void query_pre(int k, int x)
{
    if(k == 0)return;
    if(t[k].v < x)
    {
        ans = k;
        query_pre(t[k].r,x);
    }
    else query_pre(t[k].l,x);
}
 
void query_nst(int k, int x)
{
    if(k == 0)return;
    if(t[k].v > x)
    {
        ans = k;
        query_nst(t[k].l,x);
    }
    else query_nst(t[k].r,x);   
}
 
void del(int &k ,int x)
{
    if(k == 0) return;
    if(t[k].v == x)
    {
        if(t[k].w > 1)
        {
            t[k].w --;
            t[k].size --;
            return;
        }
        if(t[k].l * t[k].r == 0) k = t[k].l + t[k].r;
        else
            if(t[ t[k].l ].rnd < t[ t[k].r ].rnd) right_turn(k),del(k,x);
        else left_turn(k),del(k,x);
    }
    else if(t[k].v < x) t[k].size --,del(t[k].r,x);
    else t[k].size --, del(t[k].l,x);
     
}