LG3369 【模板】普通平衡树
题意
您需要写一种数据结构(可参考题目标题),来维护一些数,其中需要提供以下操作:
- 插入x数
- 删除x数(若有多个相同的数,因只删除一个)
- 查询x数的排名(排名定义为比当前数小的数的个数+1。若有多个相同的数,因输出最小的排名)
- 查询排名为x的数
- 求x的前驱(前驱定义为小于x,且最大的数)
- 求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 【模板】普通平衡树的更多相关文章
- luoguP3391[模板]文艺平衡树(Splay) 题解
链接一下题目:luoguP3391[模板]文艺平衡树(Splay) 平衡树解析 这里的Splay维护的显然不再是权值排序 现在按照的是序列中的编号排序(不过在这道题目里面就是权值诶...) 那么,继续 ...
- luoguP3369[模板]普通平衡树(Treap/SBT) 题解
链接一下题目:luoguP3369[模板]普通平衡树(Treap/SBT) 平衡树解析 #include<iostream> #include<cstdlib> #includ ...
- 【洛谷P3369】 (模板)普通平衡树
https://www.luogu.org/problemnew/show/P3369 Splay模板 #include<iostream> #include<cstdio> ...
- [luogu3369/bzoj3224]普通平衡树(splay模板、平衡树初探)
解题关键:splay模板题整理. 如何不加入极大极小值?(待思考) #include<cstdio> #include<cstring> #include<algorit ...
- 【模板】平衡树——Treap和Splay
二叉搜索树($BST$):一棵带权二叉树,满足左子树的权值均小于根节点的权值,右子树的权值均大于根节点的权值.且左右子树也分别是二叉搜索树.(如下) $BST$的作用:维护一个有序数列,支持插入$x$ ...
- 洛谷.3369.[模板]普通平衡树(Splay)
题目链接 第一次写(2017.11.7): #include<cstdio> #include<cctype> using namespace std; const int N ...
- 洛谷.3369.[模板]普通平衡树(fhq Treap)
题目链接 第一次(2017.12.24): #include<cstdio> #include<cctype> #include<algorithm> //#def ...
- 洛谷.3391.[模板]文艺平衡树(Splay)
题目链接 //注意建树 #include<cstdio> #include<algorithm> const int N=1e5+5; //using std::swap; i ...
- 文艺平衡Splay树学习笔记(2)
本blog会讲一些简单的Splay的应用,包括但不局限于 1. Splay 维护数组下标,支持区间reserve操作,解决区间问题 2. Splay 的启发式合并(按元素多少合并) 3. 线段树+Sp ...
- [note]fhq_treap
fhq_treap 这东西据说是某个叫范浩强的神仙搞出来的, 他的这种treap可以不用旋转并且资磁很多平衡树操作, 复杂度通过随机的键值来保证(树大致平衡,期望一次操作复杂度\(logn\)) 依靠 ...
随机推荐
- 缓存地图 ArcGIS ——Local compact and exploded tile cache layer for WPF API
ArcGISArcGIS 主页 特色 合约 图库 地图 组 帮助 我的内容 我的组织 登录 我的个人资料 帮助 管理员指南 登出 0 搜索全部内容 搜索地图 搜索图层 搜索应用程序 搜索工具 搜索 ...
- Android动画(Animations)
动画类型Android的animation由四种类型组成 XML中 alpha : 渐变透明度动画效果 scale :渐变尺寸伸缩动画效果 translate : 画面转换位置移动动画效果 ro ...
- Confluence 6 管理多目录
这个页面描述了如果在 Confluence 中定义了多个目录服务器将会发生什么样的情况.例如你可能会有一个内部目录服务器同时你还可能有连接一个 LDAP 外部服务器或者使用多种类型的其他用户目录.当你 ...
- html5- 摘自网友dudu
HTML5中新增了<canvas>画布标签,通过它,可以使用JavaScript在网页中绘制图像.<canvas>标签在网页中得到的是一个矩形空白区域,可以通过width和he ...
- memory prefix un,under,uni out1
1● un 不 非,无 打开 ,解开 ,开出 2● under ʌnd ə 向下,副 的,不足的 3● uni 单一 ,单
- 013PHP文件处理——filemtime filectime fileatime date_default_timezone_set touch
<?php /** * filemtime filectime fileatime date_default_timezone_set touch */ /*filemtime:获取文件的修改时 ...
- CCF 高速公路 tarjan求强连通分量
问题描述 某国有n个城市,为了使得城市间的交通更便利,该国国王打算在城市之间修一些高速公路,由于经费限制,国王打算第一阶段先在部分城市之间修一些单向的高速公路. 现在,大臣们帮国王拟了一个修高速公路的 ...
- SQL*Loader 详解
在 Oracle 数据库中,我们通常在不同数据库的表间记录进行复制或迁移时会用以下几种方法: 1. A 表的记录导出为一条条分号隔开的 insert 语句,然后执行插入到 B 表中2. 建立数据库间的 ...
- for each...in,for...in, for...of
一.for each ...in explanation: 该语句在对象属性的所有值上迭代指定的变量.对于每个不同的属性,执行指定的语句. 句法: for each (variable in obj ...
- Maven 打jar包,pom文件配置
以下是pom.xml文件的相关配置. <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="h ...