P3369 【模板】普通平衡树 Treap
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 原名:普通平衡树
在此鸣谢
code
treap 真是个好东西。。
#include<cstdio>
#include<algorithm>
#include<ctime>
using namespace std; const int N = ; struct Data{
int l,r,val,key,siz,cnt;
}t[N];
int Root,tn,ans; inline char nc() {
static char buf[],*p1 = buf,*p2 = buf;
return p1==p2&&(p2=(p1=buf)+fread(buf,,,stdin),p1==p2) ? EOF :*p1++;
}
inline int read() {
int x = ,f = ;char ch=nc();
for (; ch<''||ch>''; ch = nc())
if (ch == '-') f = -;
for (; ch>=''&&ch<=''; ch = nc())
x = x*+ch-'';
return x * f;
} inline void pushup(int x) {
t[x].siz = t[t[x].l].siz + t[t[x].r].siz + t[x].cnt;
}
inline void leftturn(int &k) {
int a = t[k].r;
t[k].r = t[a].l;
t[a].l = k;
t[a].siz = t[k].siz;
pushup(k);
k = a;
}
inline void rightturn(int &k) {
int a = t[k].l;
t[k].l = t[a].r;
t[a].r = k;
t[a].siz = t[k].siz;
pushup(k);
k = a;
}
void Insert(int &k,int x) {
if (k==) {
tn++;k = tn;
t[k].siz = t[k].cnt = ;
t[k].val = x;t[k].key = rand();
return ;
}
t[k].siz++;
if (t[k].val==x) t[k].cnt ++;
else if (x > t[k].val) {
Insert(t[k].r,x);
if (t[t[k].r].key < t[k].key) leftturn(k);
}
else {
Insert(t[k].l,x);
if (t[t[k].l].key < t[k].key) rightturn(k);
}
}
void Delete(int &k,int x) {
if (k==) return ;
if (t[k].val==x) {
if (t[k].cnt > ) {
t[k].cnt--;t[k].siz--;return ;
}
if (t[k].l * t[k].r == ) k = t[k].l + t[k].r;
else if (t[t[k].l].key < t[t[k].r].key) {
rightturn(k);Delete(k,x);
}
else {
leftturn(k);Delete(k,x);
}
}
else if (x > t[k].val) {
t[k].siz--;Delete(t[k].r,x);
}
else {
t[k].siz--;Delete(t[k].l,x);
}
}
int getk(int k,int x) {
if (k==) return ;
if (t[k].val==x) return t[t[k].l].siz + ;
else if (x > t[k].val)
return t[t[k].l].siz + t[k].cnt + getk(t[k].r,x);
else return getk(t[k].l,x);
}
int getkth(int k,int x) {
if (k==) return ;
if (x <= t[t[k].l].siz) return getkth(t[k].l,x);
else if (x > t[t[k].l].siz + t[k].cnt)
return getkth(t[k].r,x-t[t[k].l].siz-t[k].cnt);
else return t[k].val;
}
void getpre(int k,int x) {
if (k==) return ;
if (t[k].val < x) ans = k,getpre(t[k].r,x);
else getpre(t[k].l,x);
}
void getsuc(int k,int x) {
if (k==) return ;
if (t[k].val > x) ans = k,getsuc(t[k].l,x);
else getsuc(t[k].r,x);
} int main() {
int n = read();
while (n--){
int opt = read(),x = read();
if (opt==) Insert(Root,x);
else if (opt==) Delete(Root,x);
else if (opt==) printf("%d\n",getk(Root,x));
else if (opt==) printf("%d\n",getkth(Root,x));
else if (opt==) ans = ,getpre(Root,x),printf("%d\n",t[ans].val);
else ans = ,getsuc(Root,x),printf("%d\n",t[ans].val);
}
return ;
}
更新后的treap
#include<cstdio>
#include<algorithm>
#include<ctime> using namespace std; #define lson t[k].l
#define rson t[k].r
const int N = ; struct Data{
int l,r,val,key,siz,cnt;
}t[N];
int Root,tn,ans; inline char nc() {
static char buf[],*p1 = buf,*p2 = buf;
return p1==p2&&(p2=(p1=buf)+fread(buf,,,stdin),p1==p2) ? EOF :*p1++;
}
inline int read() {
int x = ,f = ;char ch=nc();
for (; ch<''||ch>''; ch = nc())
if (ch == '-') f = -;
for (; ch>=''&&ch<=''; ch = nc())
x = x*+ch-'';
return x * f;
} inline void pushup(int k) {
t[k].siz = t[lson].siz + t[rson].siz + t[k].cnt;
}
inline void leftturn(int &k) {
int a = rson;
rson = t[a].l;
t[a].l = k;
t[a].siz = t[k].siz;
pushup(k);
k = a;
}
inline void rightturn(int &k) {
int a = lson;
lson = t[a].r;
t[a].r = k;
t[a].siz = t[k].siz;
pushup(k);
k = a;
}
void Insert(int &k,int x) {
if (k==) {
tn++;k = tn;
t[k].siz = t[k].cnt = ;
t[k].val = x;t[k].key = rand();
return ;
}
t[k].siz++;
if (t[k].val==x) t[k].cnt ++;
else if (x > t[k].val) {
Insert(rson,x);
if (t[rson].key < t[k].key) leftturn(k);
}
else {
Insert(lson,x);
if (t[lson].key < t[k].key) rightturn(k);
}
}
void Delete(int &k,int x) {
if (k==) return ;
if (t[k].val==x) {
if (t[k].cnt > ) {
t[k].cnt--;t[k].siz--;return ;
}
if (lson * rson == ) k = lson + rson;
else if (t[lson].key < t[rson].key) {
rightturn(k);Delete(k,x);
}
else {
leftturn(k);Delete(k,x);
}
}
else if (x > t[k].val) {
t[k].siz--;Delete(rson,x);
}
else {
t[k].siz--;Delete(lson,x);
}
}
int getk(int k,int x) {
if (k==) return ;
if (t[k].val==x) return t[lson].siz + ;
else if (x > t[k].val)
return t[lson].siz + t[k].cnt + getk(rson,x);
else return getk(lson,x);
}
int getkth(int k,int x) {
if (k==) return ;
if (x <= t[lson].siz) return getkth(lson,x);
else if (x > t[lson].siz + t[k].cnt)
return getkth(rson,x-t[lson].siz-t[k].cnt);
else return t[k].val;
}
void getpre(int k,int x) {
if (k==) return ;
if (t[k].val < x) ans = k,getpre(rson,x);
else getpre(lson,x);
}
void getsuc(int k,int x) {
if (k==) return ;
if (t[k].val > x) ans = k,getsuc(lson,x);
else getsuc(rson,x);
} int main() {
int n = read();
while (n--){
int opt = read(),x = read();
if (opt==) Insert(Root,x);
else if (opt==) Delete(Root,x);
else if (opt==) printf("%d\n",getk(Root,x));
else if (opt==) printf("%d\n",getkth(Root,x));
else if (opt==) ans = ,getpre(Root,x),printf("%d\n",t[ans].val);
else ans = ,getsuc(Root,x),printf("%d\n",t[ans].val);
}
return ;
}
P3369 【模板】普通平衡树 Treap的更多相关文章
- luoguP3369[模板]普通平衡树(Treap/SBT) 题解
链接一下题目:luoguP3369[模板]普通平衡树(Treap/SBT) 平衡树解析 #include<iostream> #include<cstdlib> #includ ...
- 【模板】平衡树——Treap和Splay
二叉搜索树($BST$):一棵带权二叉树,满足左子树的权值均小于根节点的权值,右子树的权值均大于根节点的权值.且左右子树也分别是二叉搜索树.(如下) $BST$的作用:维护一个有序数列,支持插入$x$ ...
- 算法模板——平衡树Treap 2
实现功能:同平衡树Treap 1(BZOJ3224 / tyvj1728) 这次的模板有了不少的改进,显然更加美观了,几乎每个部分都有了不少简化,尤其是删除部分,这个参照了hzwer神犇的写法,在此鸣 ...
- 普通平衡树Treap(含旋转)学习笔记
浅谈普通平衡树Treap 平衡树,Treap=Tree+heap这是一个很形象的东西 我们要维护一棵树,它满足堆的性质和二叉查找树的性质(BST),这样的二叉树我们叫做平衡树 并且平衡树它的结构是接近 ...
- 2021.12.06 平衡树——Treap
2021.12.06 平衡树--Treap https://www.luogu.com.cn/blog/HOJQVFNA/qian-xi-treap-ping-heng-shu 1.二叉搜索树 1.1 ...
- hiho #1325 : 平衡树·Treap
#1325 : 平衡树·Treap 时间限制:10000ms 单点时限:1000ms 内存限制:256MB 描述 小Ho:小Hi,我发现我们以前讲过的两个数据结构特别相似. 小Hi:你说的是哪两个啊? ...
- hiho一下103周 平衡树·Treap
平衡树·Treap 时间限制:10000ms 单点时限:1000ms 内存限制:256MB 描述 小Ho:小Hi,我发现我们以前讲过的两个数据结构特别相似. 小Hi:你说的是哪两个啊? 小Ho:就是二 ...
- 【山东省选2008】郁闷的小J 平衡树Treap
小J是国家图书馆的一位图书管理员,他的工作是管理一个巨大的书架.虽然他很能吃苦耐劳,但是由于这个书架十分巨大,所以他的工作效率总是很低,以致他面临着被解雇的危险,这也正是他所郁闷的.具体说来,书架由N ...
- Hihocoder 1325 平衡树·Treap(平衡树,Treap)
Hihocoder 1325 平衡树·Treap(平衡树,Treap) Description 小Ho:小Hi,我发现我们以前讲过的两个数据结构特别相似. 小Hi:你说的是哪两个啊? 小Ho:就是二叉 ...
- HihoCoder 1325 平衡树·Treap
HihoCoder 1325 平衡树·Treap 时间限制:10000ms 单点时限:1000ms 内存限制:256MB 描述 小Ho:小Hi,我发现我们以前讲过的两个数据结构特别相似. 小Hi:你说 ...
随机推荐
- B. Game of the Rows
B. Game of the Rows time limit per test 1 second memory limit per test 256 megabytes input standard ...
- 浅谈C#解析网页
最近做了一个项目,要求获取各大主流网页上的关键信息,本人以前了解过网页爬虫的知识,所以想到了网页爬虫了实现功能 第一次尝试: 采用webclient获取远程网页的内容,然后采用正则表达式进行过滤 但, ...
- plsql过期注册
Product Code:4t46t6vydkvsxekkvf3fjnpzy5wbuhphqzserial Number:601769password:xs374ca 打开plsql工具 点击注册即可
- MariaDB 实现主从复制
實驗目的: MariaDB為MySQL的一個分支,其完全開源.無版權之虞且操作上與 MySQL 一脈相承,實際應用中非常廣泛,軟件本身很小,安裝容易,使用簡單. 但其也有缺點,指令行方式操作,無原生G ...
- Java中的break循环——通过示例学习Java编程(13)
作者:CHAITANYA SINGH 来源:https://www.koofun.com//pro/kfpostsdetail?kfpostsid=24 break语句通常用于以下两种情况: (A)使 ...
- 结合源码看nginx-1.4.0之nginx内存管理详解
目录 0. 摘要 1. nginx内存结构设计 2. nginx内存数据结构 3. nginx内存管理原理 4. 一个简单的内存模型 5. 小结 6. 参考资料 0. 摘要 内存管理,是指软件运行时对 ...
- android动画ppt整理
案例
- Writable和Comparable
WritableComparable接口相当于继承了上述两个接口的新接口 : Public interface WritableComparable<T>extends Writable, ...
- UOJ#7 NOI2014 购票 点分治+凸包二分 斜率优化DP
[NOI2014]购票 链接:http://uoj.ac/problem/7 因为太麻烦了,而且暴露了我很多学习不扎实的问题,所以记录一下具体做法. 主要算法:点分治+凸包优化斜率DP. 因为$q_i ...
- 【UML】构件图Component diagram(实现图)(转)
http://blog.csdn.net/sds15732622190/article/details/49048887 前言 下面要介绍UML中的构建图,它属于实现图的一种,五种静态图之一. 定义 ...