Code:

#include<bits/stdc++.h>
using namespace std;
struct segmenttree
{
    int l,r,cnt;
}sgt[8*100000+5];
struct option
{
    int op,x;
}opt[100005];
int rk[100005],org[100005],n;
void build(int p,int l,int r)
{
    sgt[p].l=l;sgt[p].r=r;
    if(l==r)return ;
    int mid=(l+r)>>1;
    build(p<<1,l,mid);
    build(p<<1|1,mid+1,r);
}
void update(int p)
{
    sgt[p].cnt=sgt[p<<1].cnt+sgt[p<<1|1].cnt;
}
void change(int p,int k,int d)
{
    if(sgt[p].l==sgt[p].r)
    {
        if(sgt[p].cnt+d>=0)sgt[p].cnt+=d;
        return ;
    }
    int mid=(sgt[p].l+sgt[p].r)>>1;
    if(k<=mid)change(p<<1,k,d);
    else change(p<<1|1,k,d);
    update(p);
}
int getrank(int p,int k)
{
    if(sgt[p].l==sgt[p].r)return 1;
    int mid=(sgt[p].l+sgt[p].r)>>1;
    if(k<=mid)return getrank(p<<1,k);
    else return getrank(p<<1|1,k)+sgt[p<<1].cnt;
}
int getval(int p,int k)
{
    if(sgt[p].l==sgt[p].r)return sgt[p].l;
    if(k<=sgt[p<<1].cnt)return getval(p<<1,k);
    else return getval(p<<1|1,k-sgt[p<<1].cnt);
}
int getcnt(int p,int k)
{
    if(sgt[p].l==sgt[p].r)return sgt[p].cnt;
    int mid=(sgt[p].l+sgt[p].r)>>1;
    if(k<=mid)return getcnt(p<<1,k);
    else return getcnt(p<<1|1,k);
}
int main()
{
    scanf("%d",&n);
    int i,sum=0;
    for(i=1;i<=n;i++)
    {
        scanf("%d%d",&opt[i].op,&opt[i].x);
        if(opt[i].op!=4)rk[++sum]=opt[i].x;
    }
    sort(rk+1,rk+sum+1);
    int cnt=unique(rk+1,rk+sum+1)-rk;
    for(i=1;i<=n;i++)
        if(opt[i].op!=4)
        {
            int val=lower_bound(rk+1,rk+cnt+1,opt[i].x)-rk;
            org[val]=opt[i].x;
            opt[i].x=val;
        }
    build(1,1,cnt);
    for(i=1;i<=n;i++)
    {
        int x=opt[i].x,op=opt[i].op;
        if(op==1)change(1,x,1);
        else if(op==2)change(1,x,-1);
        else if(op==3)printf("%d\n",getrank(1,x));
        else if(op==4)printf("%d\n",org[getval(1,x)]);
        else if(op==5)printf("%d\n",org[getval(1,getrank(1,x)-1)]);
        else printf("%d\n",org[getval(1,getrank(1,x)+getcnt(1,x))]);
    }
    return 0;
}

具体思想:
1、离散化维护值域动态开点
2、统计数出现的次数
3、单点修改,单点查询
其实这样想树状数组好像也可以,但我不会

具体实现:
先离散化,再线段树维护值域,每一个节点维护这个区间中目前有多少个数

于是增加/删减直接单点修改即可

对于获取排名,getrank(x)实现方法为:
1、若搜索到x,则返回一(排名定义,比x小的数个数+1)
2、若x<=区间中位数,则返回左儿子getrank(x)
3、若非前两种情况,则返回右儿子getrank(x)+左儿子的cnt

对于根据排名获取数,getval(x)实现方法为:
1、若到目标节点,则返回这个节点
2、若x<=左儿子的cnt,则返回左儿子getrank(x)
3、若非前两种情况,则返回右儿子getrank(x-左儿子的cnt)

还有一个辅助操作,getcnt(x)表示获得x出现了几次,具体实现见代码懒得讲

求前驱时,由于返回值为<x的数个数+1,直接返回getval(getrank(x)-1)即可
求后继时,由于要加上x的个数,直接返回getval(getrank(x)+getcnt(x))

注意最后要由org数组映射为原数

欢迎各位大佬参观,提出建议和指出错误

感觉像是给自己抄模板用的