题意

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

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

\(n \leq 10^5\)

分析

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










范浩强对函数式编程在OI中的应用做了很好的引入工作。

非旋式Treap的精华在于那个merge。
merge的参数要求保证x中最大的数不大于y中最小的数。
这样在合并一个子树的时候,有两种等价情况,一种是x是y的左儿子,一种是y是x的右儿子。
选择的依据是priority,这样平衡的道理就跟普通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;
}

LG3369 【模板】普通平衡树的更多相关文章

  1. luoguP3391[模板]文艺平衡树(Splay) 题解

    链接一下题目:luoguP3391[模板]文艺平衡树(Splay) 平衡树解析 这里的Splay维护的显然不再是权值排序 现在按照的是序列中的编号排序(不过在这道题目里面就是权值诶...) 那么,继续 ...

  2. luoguP3369[模板]普通平衡树(Treap/SBT) 题解

    链接一下题目:luoguP3369[模板]普通平衡树(Treap/SBT) 平衡树解析 #include<iostream> #include<cstdlib> #includ ...

  3. 【洛谷P3369】 (模板)普通平衡树

    https://www.luogu.org/problemnew/show/P3369 Splay模板 #include<iostream> #include<cstdio> ...

  4. [luogu3369/bzoj3224]普通平衡树(splay模板、平衡树初探)

    解题关键:splay模板题整理. 如何不加入极大极小值?(待思考) #include<cstdio> #include<cstring> #include<algorit ...

  5. 【模板】平衡树——Treap和Splay

    二叉搜索树($BST$):一棵带权二叉树,满足左子树的权值均小于根节点的权值,右子树的权值均大于根节点的权值.且左右子树也分别是二叉搜索树.(如下) $BST$的作用:维护一个有序数列,支持插入$x$ ...

  6. 洛谷.3369.[模板]普通平衡树(Splay)

    题目链接 第一次写(2017.11.7): #include<cstdio> #include<cctype> using namespace std; const int N ...

  7. 洛谷.3369.[模板]普通平衡树(fhq Treap)

    题目链接 第一次(2017.12.24): #include<cstdio> #include<cctype> #include<algorithm> //#def ...

  8. 洛谷.3391.[模板]文艺平衡树(Splay)

    题目链接 //注意建树 #include<cstdio> #include<algorithm> const int N=1e5+5; //using std::swap; i ...

  9. 文艺平衡Splay树学习笔记(2)

    本blog会讲一些简单的Splay的应用,包括但不局限于 1. Splay 维护数组下标,支持区间reserve操作,解决区间问题 2. Splay 的启发式合并(按元素多少合并) 3. 线段树+Sp ...

  10. [note]fhq_treap

    fhq_treap 这东西据说是某个叫范浩强的神仙搞出来的, 他的这种treap可以不用旋转并且资磁很多平衡树操作, 复杂度通过随机的键值来保证(树大致平衡,期望一次操作复杂度\(logn\)) 依靠 ...

随机推荐

  1. centos7: svbversion版本的安装配置+tortoisesvn登录验证

    centos7: svbversion版本的安装配置+tortoisesvn登录验证 命令工具:svnadmin create #创建版本库 hotcopy #版本库热备份 Islocks #打印所有 ...

  2. 雷林鹏分享:C# 多线程

    C# 多线程 线程 被定义为程序的执行路径.每个线程都定义了一个独特的控制流.如果您的应用程序涉及到复杂的和耗时的操作,那么设置不同的线程执行路径往往是有益的,每个线程执行特定的工作. 线程是轻量级进 ...

  3. LncRNA

    简介:长链非编码RNA(Long non-coding RNA, lncRNA)通过多种机制发挥其生物学功能, 这些机制包括基因印记.染色质重塑.细胞周期调控.剪接调控.mRNA降解和翻译调控等.ln ...

  4. LeetCode--171--Excel表列序号

    问题描述: 给定一个Excel表格中的列名称,返回其相应的列序号. 例如, A -> 1 B -> 2 C -> 3 ... Z -> 26 AA -> 27 AB -& ...

  5. Ivan and Burgers CodeForces - 1100F (线性基)

    大意: 给定n元素序列, m个询问$(l,r)$, 求$[l,r]$中选出任意数异或后的最大值 线性基沙茶题, 直接线段树暴力维护两个log还是能过的 #include <iostream> ...

  6. http 请求和格式

    get 请求:从指定的资源请求数据. post请求:向指定的资源提交要被处理的数据. head请求:与 GET 相同,但只返回 HTTP 报头,不返回资源实体. option请求:返回服务器支持的 H ...

  7. vnc xfce tab自动补全失效的解决方法

    edit~/.config/xfce4/xfconf/xfce-perchannel-xml/xfce4-keyboard-shortcuts.xml find the line <proper ...

  8. vuex2.0+两个小例子

    首先vuex概念比较多,一定要搞懂里面的概念,可以参考官网Vuex2.0概念,我写此文的目的是希望能对前端爱好者提供个参考,加深对vuex2.0各核心概念的理解. 废话少说,直接上干货.这是官网上的一 ...

  9. python dict sorted 排序

    https://www.cnblogs.com/linyawen/archive/2012/03/15/2398292.html 我们知道Python的内置dictionary数据类型是无序的,通过k ...

  10. FZU 2124 吃豆人 bfs

    题目链接:吃豆人 比赛的时候写的bfs,纠结要不要有vis数组设置已被访问,没有的话死循环,有的话就不一定是最优解了.[此时先到的不一定就是时间最短的.]于是换dfs,WA. 赛后写了个炒鸡聪明的df ...