模板——Treap
不得不说平衡树博大精深,除了Treap,还有splay,非旋Treap和可持久化数据结构,今天先讲讲Treap,也很感谢这位大佬的博客给予我帮助:http://www.360doc.com/content/19/0120/11/5315_810146183.shtml
Treap的核心就是Tree+Heap,即在二叉搜索树的基础上根据随机数生成的优先级使树保持堆的性质,从而实现使Treap的深度不会太大的效果
核心操作就是旋转:人工YY一下……发现旋转有左旋(Zag)和右旋(Zig)两种操作,旋转时连三条边,即原顶点和新儿子的边,新定点作为原顶点父亲的边,以及上一级父亲连向新顶点的边。顶点和儿子连接的边先处理,用&p始终维护顶点坐标,因为传入的是son[father[p]],所以p变化时它父亲的儿子会自动变化,所以通过取址可以自动连边 (rotate下一层的p是上一层的son,p变上一层son就变) (详见代码)
除了insert和delete操作中需要rotate(delete要把删除点转到叶子结点再删去,insert在插入后要旋转以维护heap的性质,不要忘记操作之后要push_up),其它的代码都和二叉搜索树一样
// luogu-judger-enable-o2
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const ll mod=;
const int N=;
const int inf=(int)2e9;
int R=; int ran()
{
static ll seed=;
seed=seed*%mod;
return (int)seed;
} struct node
{
int rnd,val,sz,ch[],num;
node(){}
node(int val,int sz,int num):val(val),sz(sz),num(num){
rnd=ran();//大根堆
ch[]=ch[]=;//和上方函数不能同时使用,若去掉该句会MLE
}
}a[];
int sum_node=;//同一节点内的相同数字的个数 void push_up(int x)
{
a[x].sz=a[x].num+a[a[x].ch[]].sz+a[a[x].ch[]].sz;
} void rotate(int &p,int d)//0:Zag 1:Zig
{
int k=a[p].ch[d^];
a[p].ch[d^]=a[k].ch[d];
a[k].ch[d]=p;
push_up(p);
push_up(k);
p=k;//传入的是son[father],father连边自动变
} void insert(int &p,int x)
{
if(!p)
{
p=++sum_node;
node tmp(x,,);
a[p]=tmp;
return;
}
if(a[p].val==x)
{
a[p].num++;
a[p].sz++;
return;
}
int d=(int)(x>a[p].val);
insert(a[p].ch[d],x);
if(a[p].rnd<a[a[p].ch[d]].rnd) rotate(p,d^);//大根堆
//本一级rotate传入的p就是上一级insert传入的son
push_up(p);
return;
} void del(int &p,int x)
{
if(!p) return;
if(a[p].val>x) del(a[p].ch[],x);
else if(a[p].val<x) del(a[p].ch[],x);
else
{
if(!a[p].ch[]&&!a[p].ch[])
{
a[p].num--; a[p].sz--;
if(a[p].num==) p=;
}
else if(a[p].ch[]&&!a[p].ch[])
{
rotate(p,);
del(a[p].ch[],x);
}
else if(!a[p].ch[]&&a[p].ch[])
{
rotate(p,);
del(a[p].ch[],x);//之前写反了
}
else
{
int d=(int)(a[a[p].ch[]].rnd>a[a[p].ch[]].rnd);
rotate(p,d);
del(a[p].ch[d],x);
}
}
push_up(p);
} int rnk(int p,int x)//以p为根的x的rank
{
if(p==) return ;//important
if(x>a[p].val)
{
return a[a[p].ch[]].sz+a[p].num+rnk(a[p].ch[],x);
}
else if(x<a[p].val)
{
return rnk(a[p].ch[],x);
}
else
{
return a[a[p].ch[]].sz+;
}
} int find(int p,int x)//已知rank查数
{
if(!p) return ;
if(a[a[p].ch[]].sz+a[p].num<x)//important(num)
{
return find(a[p].ch[],x-a[a[p].ch[]].sz-a[p].num);
}
else if(a[a[p].ch[]].sz>=x)//>=!!!
{
return find(a[p].ch[],x);
}
else
{
return a[p].val;
}
} int pre(int p,int x)
{
if(!p) return -inf;
if(a[p].val>=x)
{
return pre(a[p].ch[],x);
}
else return max(a[p].val,pre(a[p].ch[],x));
} int suc(int p,int x)
{
if(!p) return inf;
if(a[p].val<=x)
{
return suc(a[p].ch[],x);
}
else return min(a[p].val,suc(a[p].ch[],x));
} int n;
int main()
{
scanf("%d",&n);
for(int i=;i<=n;i++)
{
int opt,x;
scanf("%d%d",&opt,&x);
if(opt==) insert(R,x);//R每次会随着p改变
else if(opt==) del(R,x);
else if(opt==) printf("%d\n",rnk(R,x));
else if(opt==) printf("%d\n",find(R,x));
else if(opt==) printf("%d\n",pre(R,x));
else printf("%d\n",suc(R,x));
}
return ;
}
模板——Treap的更多相关文章
- [模板] Treap
插入x 删除x 查询排名为x的数 查询x的排名 求x的前驱.后继 //Stay foolish,stay hungry,stay young,stay simple #include<iostr ...
- 模板—treap
#include<iostream> #include<cstdio> #include<cstdlib> #define INF 0x7fffffff using ...
- 模板——Treap实现名次树
Treap 是一种通过赋予结点随机权值的一种满足堆性质的二叉搜索树,它很好的解决了二叉搜索树顺序插入组成链式的局限性. 名次树是指在treap的每个结点中添加附加域size,表示以它为根的子树的总结点 ...
- LG3369 普通平衡树
题意 维护一些数,其中需要提供以下操作: 1.插入\(x\) 2.删除\(x\)(若有多个相同的数,只删除一个) 3.查询\(x\)的排名(排名定义为比当前数小的数的个数\(+1\)) 4.查询排名为 ...
- treap树模板
///treap树模板 typedef struct Node ///节点的结构体 { Node *l,*r; int val,pri; ///节点的值和优先级 int sz; ///节点子树的节点数 ...
- BZOJ 3224 TYVJ 1728 普通平衡树 [Treap树模板]
3224: Tyvj 1728 普通平衡树 Time Limit: 10 Sec Memory Limit: 128 MB Submit: 7390 Solved: 3122 [Submit][S ...
- 三大平衡树(Treap + Splay + SBT)总结+模板[转]
Treap树 核心是 利用随机数的二叉排序树的各种操作复杂度平均为O(lgn) Treap模板: #include <cstdio> #include <cstring> #i ...
- treap完全版模板
这是我综合poj1442 3481 2352的treap操作 得到treap完全版模板.(经测AC) 结构体Tree { int key; //键值 int size; //该子树总节点个数 int ...
- Treap 模板 poj1442&hdu4557
原理可以看hihocoder上面的讲解,很清楚,不多说了. 模板抄lrj训练指南上面的. /** Treap 实现 名次树 功能: 1.找到排名为k的元素 2.值为x的元素的名次 初始化:Node* ...
随机推荐
- Pytorch模型定义的三要
首先,必须继承nn.Module这个类,要让Pytorch知道这个类是一个Module. 其次,在_init_(self)中设置需要的组件,比如(Conv,Pooling,Linear,BatchNo ...
- 精选15个国外CSS框架
转自:http://blog.bingo929.com/css-frameworks-15.html 什么是css框架 实际上还是让我们从框架说起吧.框架就是一个你可以用于你的网站项目的基本的概念上的 ...
- 5步减小你的CSS样式表
第一步:学会如何组合选择器 什么是选择器?如果你还不知道什么叫做”选择器”,你可以先参考一下w3schools.com的CSS语法概述. 未优化的CSS代码在下面的图例中,你会看到来自三个不同选择器的 ...
- vue中解决拖动和点击事件的冲突
BUG说明: 鼠标上下方向拖拽,如果松开时鼠标位于悬浮按钮上会默认执行click事件,经验证,click事件与mouse事件的执行顺序为onmousedown =>onmouseup => ...
- Java常用文件下载与查找的URL
Java JDK: http://www.oracle.com/technetwork/java/javase/downloads/index.html Tomcat: http://tomcat.a ...
- 8_InlineHook
1 shellcode低2Gb警告.应使用高2GB 稳定 : 在内核挂钩子: 由于每个进程的低2gb 的数据是不同的:所以 在内核挂钩子 因该把 代码 放在 高 2gb. 方法1(申请): 比如 使用 ...
- VGDB提示
由于之前地址的版本在未安装.Net 4.0的电脑上安装会出现插件使用装载失败的问题,已更新,新地址为:http://pan.baidu.com/s/1xdnuD,此版本需要.Net 2.0.
- 数据库MySQL--修改数据表
创建数据库::create database 数据库名: 如果数据不存在则创建,存在不创建:Create database if not exists 数据库名 ; 删除数据库::drop datab ...
- js里json和eval()
JSON * - JS中的对象只有JS自己认识,其他的语言都不认识 * - JSON就是一个特殊格式的字符串,这个字符串可以被任意的语言所识别, * 并且可以转换为任意语言中的对象,JSON在开发中主 ...
- Appium 微信 webview 的自动化技术
Appium 微信 webview 的自动化技术 最近好多人问微信webview自动化的事情, 碰巧我也在追微信webview的自动化和性能分析方法. 先发出来一点我的进展给大家参考下. 此方法用 ...