题意

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

  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. 错误代码0x00000001,好多软件连不了网,求助~(WIN7/win8/win9/win10)

    解决办法: 以管理员身份运行命令行,在弹出的窗口中运行如下命令: netsh winsock reset catalog netsh int ip reset reset.log hit 让被阻止了的 ...

  2. LeetCode--038--报数(*)

    问题描述: 报数序列是指一个整数序列,按照其中的整数的顺序进行报数,得到下一个数.其前五项如下: 1. 1 2. 11 3. 21 4. 1211 5. 111221 1 被读作  "one ...

  3. linux--多进程进行文件拷贝

    学习IO的时候,我们都曾经利用文件IO函数,标准IO函数都实现了对文件的拷贝, 对某一个文件进行拷贝时,我们可以考虑一下几种方式: a.单进程拷贝: 假设某一文件需要拷贝100字节,每一个时间片可以完 ...

  4. hdu 1226 bfs+余数判重+大数取余

    题目: 超级密码 Time Limit: 20000/10000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)Total ...

  5. HDOJ1005

    #include "iostream" using namespace std; int fun(int A,int B,int n) { ,y = ,z; || n == ) ; ...

  6. OAF 获取页面路径

    --模糊查询某个页面 SELECT * FROM JDR_PATHS jp WHERE JP.PATH_NAME LIKE '%XXXX%'; --精确的查找过程 -- DocID --参数通过关于此 ...

  7. HttpServletResponse输出的中文乱码

    HttpServletResponse输出有两种格式,一种是字符流,一种是字节流. 1.字符流 // 这句话的意思,是让浏览器用utf8来解析返回的数据,即设置客户端解析的编码 response.se ...

  8. turbine源码分析

    turbine源码分析 1.turbine架构设计 一切从InstanceDiscovery模块开始,该模块提供所有的主机信息.它会定期的发送更新,ConnectionManager负责创建连接到主机 ...

  9. IOS UI总结

    一.UIView常见属性 1.frame  位置和尺寸(以父控件的左上角为原点(0,0)) 2.center 中点(以父控件的左上角为原点(0,0)) 3.bounds  位置和尺寸(以自己的左上角为 ...

  10. 算法笔记——C/C++语言基础篇(已完结)

    开始系统学习算法,希望自己能够坚持下去,期间会把常用到的算法写进此博客,便于以后复习,同时希望能够给初学者提供一定的帮助,手敲难免存在错误,欢迎评论指正,共同学习.博客也可能会引用别人写的代码,如有引 ...