维护当前节点代表值出现的次数。

题目描述
您需要写一种数据结构(可参考题目标题),来维护一些数,其中需要提供以下操作:

1。插入x数
2。删除x数(若有多个相同的数,因只删除一个)
3。查询x数的排名(排名定义为比当前数小的数的个数+1。若有多个相同的数,因输出最小的排名)
4。查询排名为x的数
5。求x的前驱(前驱定义为小于x,且最大的数)
6。求x的后继(后继定义为大于x,且最小的数)
输入格式
第一行为n,表示操作的个数,下面n行每行有两个数opt和x,opt表示操作的序号( 1≤opt≤6 )

输出格式
对于操作3,4,5,6每行输出一个数,表示对应答案

输入输出样例
输入 #1 复制
10
1 106465
4 1
1 317721
1 460929
1 644985
1 84185
1 89851
6 81968
1 492737
5 493598
输出 #1 复制
106465
84185
492737
说明/提示
时空限制:1000ms,128M

1.n的数据范围: n≤100000

2.每个数的数据范围: [-{10}^7 , {10}^7]
来源:Tyvj1728 原名:普通平衡树

在此鸣谢

权值线段树搞搞就好啦。

#include<iostream>
#include<cstdio>
#include<cstring>
#include<string>
#include<cmath>
#include<algorithm>
#include<queue>
#define ll long long
#define llu unsigned ll
using namespace std;
const int mod=1e9+7;
const int inf=0x3f3f3f3f;
const ll lnf=0x3f3f3f3f3f3f3f3f;
const int maxn=100100;
int id[maxn],a[maxn],b[maxn];
struct node
{
    int l,r;
    int sum;
}t[maxn<<2];

void pushup(int cnt)
{
    t[cnt].sum=t[cnt<<1].sum+t[cnt<<1|1].sum;
}

void build(int l,int r,int cnt)
{
    t[cnt].l=l,t[cnt].r=r;
    t[cnt].sum=0;
    if(l==r) return ;
    int mid=(l+r)>>1;
    build(l,mid,cnt<<1);
    build(mid+1,r,cnt<<1|1);
}

void change12(int pos,int val,int cnt)
{
    if(t[cnt].l==t[cnt].r)
    {
        t[cnt].sum+=val;
        if(t[cnt].sum<0) t[cnt].sum=0;
        return ;
    }
    if(pos<=t[cnt<<1].r) change12(pos,val,cnt<<1);
    else change12(pos,val,cnt<<1|1);
    pushup(cnt);
}

int ask3(int l,int r,int cnt)
{
    if(l>r) return 0;
    if(l<=t[cnt].l&&t[cnt].r<=r)
    {
        return t[cnt].sum;
    }
    int ans=0;
    if(l<=t[cnt<<1].r) ans+=ask3(l,r,cnt<<1);
    if(r>=t[cnt<<1|1].l) ans+=ask3(l,r,cnt<<1|1);
    return ans;
}

int ask4(int val,int cnt)
{
    if(t[cnt].sum<val) return 0;
    if(t[cnt].l==t[cnt].r)
    {
        return t[cnt].l;
    }
    if(val<=t[cnt<<1].sum) return ask4(val,cnt<<1);
    else return ask4(val-t[cnt<<1].sum,cnt<<1|1);
}

int ask5(int pos)
{
    int ans=ask3(1,pos-1,1);
    return ask4(ans,1);
}

int ask6(int pos)
{
    int ans=ask3(1,pos,1);
    return ask4(ans+1,1);
}

int main(void)
{
    int n;
    scanf("%d",&n);
    int pt=0;
    for(int i=1;i<=n;i++)
    {
        scanf("%d%d",&id[i],&a[i]);
        if(id[i]!=4) b[++pt]=a[i];
    }

    sort(b+1,b+pt+1);
    int cnt=unique(b+1,b+pt+1)-(b+1);

    build(1,cnt,1);

    for(int i=1;i<=n;i++)
        if(id[i]!=4)a[i]=lower_bound(b+1,b+cnt+1,a[i])-b;

    for(int i=1;i<=n;i++)
    {
        if(id[i]==1)
            change12(a[i],1,1);
        else if(id[i]==2)
            change12(a[i],-1,1);
        else if(id[i]==3)
            printf("%d\n",ask3(1,a[i]-1,1)+1);
        else if(id[i]==4)
            printf("%d\n",b[ask4(a[i],1)]);
        else if(id[i]==5)
            printf("%d\n",b[ask5(a[i])]);
        else if(id[i]==6)
            printf("%d\n",b[ask6(a[i])]);
    }
    return 0;
}