洛谷 P3369 普通平衡树

本来是想练习Splay的,但是,又写了线段树。。。。

线段树写起来很好理解。

离散化后对权值建立一颗线段树就可以了。

#include<bits/stdc++.h>
using namespace std;
#define LL long long
#define pb(x) push_back(x)
#define sca(x) scanf("%d",&x)
#define N 100005
struct node
{
    int op,x;
}a[N];

vector<int>V;
int sum[N*4];

void upd(int rt,int l,int r,int pos,int val)
{
    sum[rt]+=val;
    if(l==r)return ;
    int m=(l+r)>>1;
    if(pos<=m)upd(rt<<1,l,m,pos,val);
    else upd(rt<<1|1,m+1,r,pos,val);
}

int ask(int rt,int l,int r,int ql,int qr)
{
    if(l>=ql && r<=qr)return sum[rt];
    int ans=0;
    int m=(l+r)>>1;
    if(ql<=m) ans+=ask(rt<<1,l,m,ql,qr);
    if(qr>m)ans+=ask(rt<<1|1,m+1,r,ql,qr);
    return ans;
}

int query(int rt,int l,int r,int k)
{
    if(l==r)return l;
    int res=sum[rt<<1];
    int m=(l+r)>>1;
    if(res>=k)return query(rt<<1,l,m,k);
    else return query(rt<<1|1,m+1,r,k-res);
}

int main()
{
    int n;
    sca(n);
    for(int i=1;i<=n;i++)
    {
        scanf("%d%d",&a[i].op,&a[i].x);
        if(a[i].op!=4)
        V.pb(a[i].x);
    }
    sort(V.begin(),V.end());
    unique(V.begin(),V.end());
    int now;
    for(int i=1;i<=n;i++)
    {
        int op=a[i].op;
        if(op!=4)a[i].x=lower_bound(V.begin(),V.end(),a[i].x)-V.begin()+1;
        if(op==1)upd(1,1,N,a[i].x,1);
        if(op==2)upd(1,1,N,a[i].x,-1);
        if(op==3)printf("%d\n",a[i].x-1==0?1:ask(1,1,N,1,a[i].x-1)+1);
        if(op==4)printf("%d\n",V[query(1,1,N,a[i].x)-1]);
        if(op==5)
        {
            if(a[i].x-1==0)now=0;
            else now=ask(1,1,N,1,a[i].x-1);
            printf("%d\n",V[query(1,1,N,now)-1]);
        }
        if(op==6)
        {
            now=ask(1,1,N,1,a[i].x)+1;
            printf("%d\n",V[query(1,1,N,now)-1]);
        }
    }
}

猜你喜欢

转载自blog.csdn.net/weixin_40894017/article/details/88656723
今日推荐