LG3369 【模板】普通平衡树

题意

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

  1. 插入x数
  2. 删除x数(若有多个相同的数,因只删除一个)
  3. 查询x数的排名(排名定义为比当前数小的数的个数+1。若有多个相同的数,因输出最小的排名)
  4. 查询排名为x的数
  5. 求x的前驱(前驱定义为小于x,且最大的数)
  6. 求x的后继(后继定义为大于x,且最小的数)

\(n \leq 10^5\)

分析

用范浩强Treap实现。具体原理:









代码

#include<cstdlib>
#include<cstdio>
#include<cmath>
#include<cstring>
#include<ctime>
#include<iostream>
#include<string>
#include<vector>
#include<list>
#include<deque>
#include<stack>
#include<queue>
#include<map>
#include<set>
#include<bitset>
#include<algorithm>
#include<complex>
#pragma GCC optimize ("O0")
using namespace std;
template<class T> inline T read(T&x)
{
    T data=0;
    int w=1;
    char ch=getchar();
    while(!isdigit(ch))
    {
        if(ch=='-')
            w=-1;
        ch=getchar();
    }
    while(isdigit(ch))
        data=10*data+ch-'0',ch=getchar();
    return x=data*w;
}
typedef long long ll;
const int INF=0x7fffffff;

const int MAXN=1e5+7;

int sz;
struct Treap
{
    int val[MAXN],pri[MAXN];
    int ch[MAXN][2],siz[MAXN];
    
    void pushup(int x)
    {
        siz[x]=siz[ch[x][0]]+1+siz[ch[x][1]];
    }
    
    int new_node(int v)
    {
        val[++sz]=v,
        pri[sz]=rand()<<15|rand();
        ch[sz][0]=ch[sz][1]=0,
        siz[sz]=1;
        return sz;
    }
    
    int merge(int x,int y)
    {
        if(!x||!y)
            return x+y;
        if(pri[x]<pri[y])
        {
            ch[x][1]=merge(ch[x][1],y);
            pushup(x);
            return x;
        }
        else
        {
            ch[y][0]=merge(x,ch[y][0]);
            pushup(y);
            return y;
        }
    }
    
    void split(int now,int v,int&x,int&y)
    {
        if(!now)
            x=y=0;
        else
        {
            if(val[now]<=v)
            {
                x=now,split(ch[now][1],v,ch[now][1],y);
            }
            else
            {
                y=now,split(ch[now][0],v,x,ch[now][0]);
            }
            pushup(now);
        }
    }
    
    void ins(int&now,int v)
    {
        int x,y;
        split(now,v,x,y);
        now=merge(merge(x,new_node(v)),y);
    }
    
    void del(int&now,int v)
    {
        int x,y,z;
        split(now,v,x,z);
        split(x,v-1,x,y);
        y=merge(ch[y][0],ch[y][1]);
        now=merge(merge(x,y),z);
    }
    
    int rank(int&now,int v)
    {
        int x,y;
        split(now,v-1,x,y);
        int ans=siz[x]+1;
        now=merge(x,y);
        return ans;
    }
    
    int kth(int now,int k)
    {
        while(1)
        {
            if(k<=siz[ch[now][0]])
                now=ch[now][0];
            else if(k==siz[ch[now][0]]+1)
                return now;
            else
                k-=siz[ch[now][0]]+1,now=ch[now][1];
        }
    }
    
    int pre(int&now,int v)
    {
        int x,y;
        split(now,v-1,x,y);
        int ans=kth(x,siz[x]);
        now=merge(x,y);
        return ans;
    }
    
    int suc(int&now,int v)
    {
        int x,y;
        split(now,v,x,y);
        int ans=kth(y,1);
        now=merge(x,y);
        return ans;
    }
}T;

int main()
{
//  freopen(".in","r",stdin);
//  freopen(".out","w",stdout);
    srand(20030506);
    int root=0;
    int n;
    read(n);
    while(n--)
    {
        static int opt,x;
        read(opt);read(x);
        if(opt==1) // insert
        {
            T.ins(root,x);
        }
        else if(opt==2) // delete
        {
            T.del(root,x);
        }
        else if(opt==3) // rank
        {
            printf("%d\n",T.rank(root,x));
        }
        else if(opt==4) // kth
        {
            printf("%d\n",T.val[T.kth(root,x)]);
        }
        else if(opt==5) // precursor
        {
            printf("%d\n",T.val[T.pre(root,x)]);
        }
        else // successor
        {
            printf("%d\n",T.val[T.suc(root,x)]);
        }
    }
//  fclose(stdin);
//  fclose(stdout);
    return 0;
}

猜你喜欢

转载自www.cnblogs.com/autoint/p/9707042.html
今日推荐