[luogu P3369]【模板】普通平衡树(Treap/SBT)
[luogu P3369]【模板】普通平衡树(Treap/SBT)
题目描述
您需要写一种数据结构(可参考题目标题),来维护一些数,其中需要提供以下操作:
插入x数
删除x数(若有多个相同的数,因只删除一个)
查询x数的排名(排名定义为比当前数小的数的个数+1。若有多个相同的数,因输出最小的排名)
查询排名为x的数
求x的前驱(前驱定义为小于x,且最大的数)
- 求x的后继(后继定义为大于x,且最小的数)
输入输出格式
输入格式:
第一行为n,表示操作的个数,下面n行每行有两个数opt和x,opt表示操作的序号( 1 \leq opt \leq 61≤opt≤6 )
输出格式:
对于操作3,4,5,6每行输出一个数,表示对应答案
输入输出样例
10 1 106465 4 1 1 317721 1 460929 1 644985 1 84185 1 89851 6 81968 1 492737 5 493598
106465 84185 492737
说明
时空限制:1000ms,128M
1.n的数据范围: n \leq 100000n≤100000
2.每个数的数据范围: [-{10}^7, {10}^7][−107,107]
来源:Tyvj1728 原名:普通平衡树
在此鸣谢
用一下午的时间打了一发treap(第一次打),感觉还挺好,实现起来没有其他平衡树高。。
然后。。主要是操作方便,旋转容易(主要依赖于树堆性质和随机期望)。。
不说了,直接贴板子。。
code:
再来一发链表指针版的(据说写大数据结构链表很常用)——
code:
%:pragma GCC optimize()
#include<bits/stdc++.h>
using namespace std;
int ans;
class tnode{
private:
];
public:
tnode() {ch[]=ch[]=;}
inline void newnode(tnode* &cur,int x) {
cur=]=cur->ch[]=,cur->v=x,cur->s=cur->c=,cur->k=rand();
}
inline void update(tnode* cur) {
cur->s=cur->c;
]!=) cur->s+=cur->ch[]->s;
]!=) cur->s+=cur->ch[]->s;
}
inline void rotate(tnode* &cur,int dir) {
tnode *tmp=cur->ch[dir^]->ch[dir];
]->ch[dir]==) cur->ch[dir^]->ch[dir]=new tnode;
cur->ch[dir^]->ch[dir]=cur;
cur=cur->ch[dir^];
cur->ch[dir]->ch[dir^]=tmp;
update(cur->ch[dir]);
update(cur);
}
inline void insert(tnode* &cur,int x) {
if (cur==NULL) {newnode(cur,x); return;}
if (cur->v==x) {cur->c++; cur->s++; return;}
bool p=cur->v<x;
insert(cur->ch[p],x);
);
else update(cur);
}
inline void remove(tnode* &cur,int x) {
if (!cur) return;
if (cur->v==x) {
) {cur->c--; cur->s--; return;}
]&&!cur->ch[]) {cur=; return;}
]||!cur->ch[]) {
cur=cur->ch[]?cur->ch[]:cur->ch[]; return;
}
]->k<cur->ch[]->k;
rotate(cur,p);
remove(cur->ch[p],x);
update(cur);
return;
}
bool p=cur->v<x;
remove(cur->ch[p],x);
update(cur);
}
inline int x_rank(tnode* cur,int x) {
;
;
]!=) s=cur->ch[]->s;
;
],x);
],x);
}
inline int rank_x(tnode* cur,int x) {
;
;
]!=) s=cur->ch[]->s;
&&x<=s+cur->c) return cur->v;
) ],x);
],x-s-cur->c);
}
inline void x_pre(tnode* cur,int x) {
if (!cur) return;
],x);
],x);
}
inline void x_suc(tnode* cur,int x) {
if (!cur) return;
],x);
],x);
}
}t,*root;
inline int read() {
,f=; char ch=getchar();
:,ch=getchar();
+ch-',ch=getchar();
return x*f;
}
int main() {
srand();
for (int Q=read(),o,x; Q; --Q) {
o=read(),x=read();
switch (o) {
: t.insert(root,x); break;
: t.remove(root,x); break;
: printf("%d\n",t.x_rank(root,x)); break;
: printf("%d\n",t.rank_x(root,x)); break;
: t.x_pre(root,x); printf("%d\n",ans); break;
: t.x_suc(root,x); printf("%d\n",ans); break;
}
}
;
}
upd 2017/11/18:
学了一下splay,写了一下,神tm好难写啊。。。
题解过段时间补吧。
code:
#pragma GCC optimize(2)
#include <cstdio>
namespace OJ{
void Online_Judge() {
#ifndef ONLINE_JUDGE
freopen("in.txt","r",stdin);
freopen("out.txt","w",stdout);
#endif
}
} using namespace OJ;
namespace fastIO {
#define gec(c) getchar(c)
#define puc(c) putchar(c)
char ch;
inline int read() {
,f=; ch=gec();
') {
if (ch=='-') f=-f;
ch=gec();
}
') {
x=(x<<)+(x<<)+ch-';
ch=gec();
}
return x*f;
}
];
template <class T> inline void write(T x) {
) {
puc('); return;
}
) {
x=-x,puc('-');
}
; x; x/=) w[++cnt]=x%;
);
}
inline void newline() {
puc('\n');
}
} using namespace fastIO;
#define Splay node
class Splay {
private:
int s,t,v;
node* c[];
public:
node () {
s=t=;
c[]=c[]=c[]=;
}
node* newnode (int v) ;
bool dir (node* x) ;
void upd (node* x) ;
void rot (node* x) ;
void splay (node* x,node* a) ;
void find (int v) ;
void insert (node* &x,int v) ;
void erase (int v) ;
int rank (int v) ;
int kth (node* x,int v) ;
int pre (int v) ;
int suc (int v) ;
} t,*r,*ori,*g;
node* Splay::newnode (int v) {
node* ret=new node();
ret->v=v;
return ret;
}
bool Splay::dir (node* x) {
]->c[]) ;
]->c[]==x;
}
void Splay::upd (node* x) {
x->s=x->t;
]) x->s+=x->c[]->s;
]) x->s+=x->c[]->s;
}
void Splay::rot (node* x) {
];
]) y->c[]->c[dir(y)]=x;
x->c[]=y->c[];
y->c[p]=x->c[p^];
]) x->c[p^]->c[]=y;
x->c[p^]=y;
y->c[]=x;
upd(y),upd(x);
}
void Splay::splay (node* x,node* o) {
]==o) return;
]!=o; ) {
]->c[]==o) {
rot(x);
if (!o) r=x;
return;
}
])) rot(x),rot(x);
]),rot(x);
}
if (!o) r=x;
}
void Splay::find (int v) {
for (g=r; g->v!=v; g=g->c[v>g->v]) ;
splay(g,);
}
void Splay::insert (node* &x,int v) {
if (!x) {
x=g=newnode(v);
return;
}
if (v==x->v) {
++x->s,++x->t,g=x;
return;
}
insert(x->c[v>x->v],v);
x->c[v>x->v]->c[]=x;
upd(x);
}
void Splay::erase (int v) {
find(v);
) {
--r->s,--r->t;
return;
}
]||!r->c[]) {
]) r=r->c[],r->c[]=; else
]) r=r->c[],r->c[]=;
;
return;
}
]; g->c[]; g=g->c[]) ;
splay(g,r);
g->c[]=,g->c[]=r->c[];
]) g->c[]->c[]=g;
r=g,upd(r);
}
int Splay::pre (int v) {
insert(r,v);
splay(g,);
]; g->c[]; g=g->c[]) ;
int ret=g->v;
erase(v);
return ret;
}
int Splay::suc (int v) {
insert(r,v);
splay(g,);
]; g->c[]; g=g->c[]) ;
int ret=g->v;
erase(v);
return ret;
}
int Splay::rank (int v) {
find(v);
splay(g,);
]?r->c[]->s:;
;
}
int Splay::kth (node* x,int v) {
;
]?:x->c[]->s;
if (v>s&&v<=s+x->t) return x->v; else
],v);
],v-s-x->t);
}
int Q;
int main() {
Online_Judge();
r=,Q=read();
; q<=Q; ++q) {
int o=read(),x=read();
switch (o) {
:
t.insert(r,x),t.splay(g,);
break;
:
t.erase(x);
break;
:
write(t.rank(x)),newline();
break;
:
write(t.kth(r,x)),newline();
break;
:
write(t.pre(x)),newline();
break;
:
write(t.suc(x)),newline();
break;
}
}
;
}
[luogu P3369]【模板】普通平衡树(Treap/SBT)的更多相关文章
- luoguP3369[模板]普通平衡树(Treap/SBT) 题解
链接一下题目:luoguP3369[模板]普通平衡树(Treap/SBT) 平衡树解析 #include<iostream> #include<cstdlib> #includ ...
- 【模板】平衡树——Treap和Splay
二叉搜索树($BST$):一棵带权二叉树,满足左子树的权值均小于根节点的权值,右子树的权值均大于根节点的权值.且左右子树也分别是二叉搜索树.(如下) $BST$的作用:维护一个有序数列,支持插入$x$ ...
- 数组splay ------ luogu P3369 【模板】普通平衡树(Treap/SBT)
二次联通门 : luogu P3369 [模板]普通平衡树(Treap/SBT) #include <cstdio> #define Max 100005 #define Inline _ ...
- 替罪羊树 ------ luogu P3369 【模板】普通平衡树(Treap/SBT)
二次联通门 : luogu P3369 [模板]普通平衡树(Treap/SBT) 闲的没事,把各种平衡树都写写 比较比较... 下面是替罪羊树 #include <cstdio> #inc ...
- 红黑树 ------ luogu P3369 【模板】普通平衡树(Treap/SBT)
二次联通门 : luogu P3369 [模板]普通平衡树(Treap/SBT) 近几天闲来无事...就把各种平衡树都写了一下... 下面是红黑树(Red Black Tree) 喜闻乐见拿到了luo ...
- 洛谷P3369 【模板】普通平衡树(Treap/SBT)
洛谷P3369 [模板]普通平衡树(Treap/SBT) 平衡树,一种其妙的数据结构 题目传送门 题目描述 您需要写一种数据结构(可参考题目标题),来维护一些数,其中需要提供以下操作: 插入x数 删除 ...
- AC日记——【模板】普通平衡树(Treap/SBT) 洛谷 P3369
[模板]普通平衡树(Treap/SBT) 思路: 劳资敲了一个多星期: 劳资终于a了: 劳资一直不a是因为一个小错误: 劳资最后看的模板: 劳资现在很愤怒: 劳资不想谈思路!!! 来,上代码: #in ...
- P3369 【模板】普通平衡树 Treap
P3369 [模板]普通平衡树(Treap/SBT) 题目描述 您需要写一种数据结构(可参考题目标题),来维护一些数,其中需要提供以下操作: 插入x数 删除x数(若有多个相同的数,因只删除一个) 查询 ...
- 算法模板——平衡树Treap 2
实现功能:同平衡树Treap 1(BZOJ3224 / tyvj1728) 这次的模板有了不少的改进,显然更加美观了,几乎每个部分都有了不少简化,尤其是删除部分,这个参照了hzwer神犇的写法,在此鸣 ...
随机推荐
- 012-docker-安装-fabric:1.4
一.准备工作 linux 版本.docker.docker-compose go安装且版本较新 uname -a docker --version docker-compose --version g ...
- ndarray的用法总结
#发现ndarray的一维,二维都可以用[i][j], 它们都是下标索引的连用, 比如j表示第j个元素;#二维ndarray可以用[m, n]来进行行列的操作,类似matlab中的用法.取某一列是[: ...
- [js]js设计模式-原型模式
构造函数模型- 对象的属性和方法每人一份 function createJs(name, age) { this.name = name; this.age = age; this.writeJs = ...
- 小程序movable-area置于顶层遮盖下方元素无法操作的解决方案
小程序项目中有个需求,右下角按钮可以在页面中随意拖动,此时查看文档找到了一个自带的标签可以实现此功能,代码如下 <movable-area> <movable-view x=&quo ...
- linux下查看CPU、内存、磁盘信息
1.查看CPU信息# 总核数 = 物理CPU个数 X 每颗物理CPU的核数 # 总逻辑CPU数 = 物理CPU个数 X 每颗物理CPU的核数 X 超线程数 # 查看物理CPU个数cat /proc/c ...
- 【UML】NO.53.EBook.5.UML.1.013-【UML 大战需求分析】- 组合结构图(Composition Structure Diagram)
1.0.0 Summary Tittle:[UML]NO.52.EBook.1.UML.1.012-[UML 大战需求分析]- 交互概览图(Interaction Overview Diagram) ...
- 深入理解Java虚拟机4-chap6-斗者1星
一.JVM语言无关性 1.以字节码为基础(Class文件为一组以8位字节为基础单位的二进制流),JVM与Class文件关联,而非与Java语言关联 2.代码编译从本地码(Native Code)转为字 ...
- vue项目中postcss-pxtorem的使用及webpack中的配置 css中单位px和em,rem的区别
移动手机版要求我们在制作嵌入h5的时候去适配不同的手机.适配有多重模式,有flex.百分比等.字体大小的控制也有px.百分比.rem等单位,webpack中 px转rem. vue项目中postcss ...
- 【awk】提取文件第一列
生信数据文件一般是按列分开的,如果我们只想简单的提取一列而不是费尽周折写个程序提取哪一列的话,awk作为一个非常好用的文档处理工具,我们现在来简单看一下他的一些功能: awk '{print $1}' ...
- 如何利用cURL和python对服务端和web端进行接口测试
工具描述 cURL是利用URL语法在命令行方式下工作的文件传输工具,是开源爱好者编写维护的免费工具,支持包括Windows.Linux.Mac等数十个操作系统,最新版本为7.27.0,但是我推荐大家使 ...