【Treap模板详细注释】BZOJ3224-普通平衡树
模板题:D错因见注释
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
using namespace std;
const int INF=0x7fffffff;
struct treap
{
treap* lson;
treap* rson;
int key;//该节点的值
int priority;//优先级
int size;//该节点以及其子树的大小
int cnt;//当前值的数字的个数
int lsize()//返回左子树的大小
{
if (lson==NULL) return ;
else return lson->size;
}
int rsize()//返回右子树的大小
{
if (rson==NULL) return ;
else return rson->size;
} treap()
{
size=cnt=;//这里初始值应该是1而不是0
priority =rand();//随机生成优先级
lson=rson=NULL;
}
};
treap* root=NULL;
int n; void update(treap* &rt)//【【Attention】】要写成*&
{
/*旋转后进行的操作更新size大小=cnt+左子树size+右子树size*/
rt->size=rt->cnt;
rt->size+=rt->lsize();
rt->size+=rt->rsize();
} void RightRotate(treap* &rt)
{
/*画图模拟一下:D*/
treap* tmp=rt->lson;
rt->lson=tmp->rson;
tmp->rson=rt;
update(rt);
update(tmp);
rt=tmp;
} void LeftRotate(treap* &rt)
{
treap* tmp=rt->rson;
rt->rson=tmp->lson;
tmp->lson=rt;
update(rt);
update(tmp);
rt=tmp;
} void insert(treap*&rt,int x)
{
/*
如果当前根节点是空的,那么新建一棵平衡树;
如果当前的x和根节点的数值大小一样,则直接在根节点累加个数;
如果当前x小于根节点的数值,那么向左子树搜索。回溯后如果左边的优先级大于根节点,则右旋
如果当前x小于根节点的数值,那么向右子树搜索。回溯后如果右边的优先级大于根节点,则左旋
*/
if (rt==NULL)
{
rt=new treap;
rt->key=x;
}
else if (x==rt->key)
{
rt->size++;
rt->cnt++;
}
else if (x<rt->key)
{
insert(rt->lson,x);
if (rt->lson->priority>rt->priority) RightRotate(rt);
update(rt);
}
else
{
insert(rt->rson,x);
if (rt->rson->priority>rt->priority) LeftRotate(rt);
update(rt);
}
} void del(treap* &rt,int x)
{
/*
如果当前根节点的key就是要删除的那个值
(1)如果当前数值的个数大于1个,直接减去cnt和size即可;
(2)如果左子树是空的,这将根节点保存给临时变量,根节点等于它的右子树,释放原来根节点内存;
(3)右子树为空同理;
(4)如果左右子树均不为空,比较两者的优先级。如果左子树优先级大则右旋,反之左旋。
如果当前根节点的key不是要删除的那个值
(1)如果x<key,则搜索左子树;
(2) 否则搜索右子树。
*/
if (x==rt->key)
{
if (rt->cnt>)
{
rt->cnt--;
rt->size--;
}
else if (rt->lson==NULL)
{
treap* tmp=rt;
rt=rt->rson;
delete tmp;
}
else if (rt->rson==NULL)
{
treap* tmp=rt;
rt=rt->lson;
delete tmp;
}
else
{
if (rt->lson->priority>rt->rson->priority)
{
RightRotate(rt);
del(rt->rson,x);
}
else
{
LeftRotate(rt);
del(rt->lson,x);
}
}
}
else
{
if (rt->key>x) del(rt->lson,x);
else del(rt->rson,x);
}
if (rt!=NULL) update(rt);
} int getrank(treap* &rt,int x)
{
/*
如果当前的key等于要询问的数,直接返回排名(左子树的大小+1)
如果当前的key大于要询问的数,进入左子树查询并返回排名
如果当前的key小于要询问的树,则返回的排名=(左子树大小+当前节点数的个数+它在右子树中的排名)
*/
if (rt->key==x) return (rt->lsize()+);
if (x<rt->key) return (getrank(rt->lson,x));
return (getrank(rt->rson,x)+rt->lsize()+rt->cnt);
} int getnum(treap* &rt,int x)
{
/*
如果需要询问的排名属于当前节点的范围(左子树个数+1~左子树个数+当前节点数的个数),则直接返回当前的key
如果要询问的排名在左子树,则前往左子树询问排名
如果要询问的排名在右子树,则前往右子树询问排名,且要询问的排名=排名-左子树的大小-当前节点代表的数的个数
*/
if (rt->lsize()+<=x && x<=rt->lsize()+rt->cnt) return rt->key;
if (x<=rt->lsize()) return getnum(rt->lson,x);
return getnum(rt->rson,x-rt->lsize()-rt->cnt);
} int pre(treap* &rt,int x)
/*
如果当前节点的值小于x,则取它和ans中较大的那个,并继续搜索右子树
如果当前节点的值大于等于x,则继续搜索左子树
*/
{
int ans=-INF;
treap* tmp=rt;
while (tmp)
{
if (tmp->key<x)
/*尴尬,这整个子程序的tmp->key都手残敲成了tmp->key...下次注意:D*/
{
ans=max(tmp->key,ans);
tmp=tmp->rson;
}
else tmp=tmp->lson;
}
return ans;
} int suc(treap* &rt,int x)
/*与pre类似*/
{
int ans=INF;
treap* tmp=rt;
while (tmp)
{
if (tmp->key>x)
{
ans=min(tmp->key,ans);
tmp=tmp->lson;
}
else tmp=tmp->rson;
}
return ans;
} void option()
{
int opt,x;
scanf("%d%d",&opt,&x);
if (opt==) insert(root,x);
else if (opt==) del(root,x);
else if (opt==) printf("%d\n",getrank(root,x));
else if (opt==) printf("%d\n",getnum(root,x));
else if (opt==) printf("%d\n",pre(root,x));
else if (opt==) printf("%d\n",suc(root,x));
} void release(treap* &rt)
{
if (rt->lson) release(rt->lson);
if (rt->rson) release(rt->rson);
free(rt);
} int main()
{
scanf("%d",&n);
for (int i=;i<n;i++) option();
release(root);
return ;
}
【Treap模板详细注释】BZOJ3224-普通平衡树的更多相关文章
- 【强连通分量】 Kosaraju和Tarjan算法 (标准模板+详细注释)
codevs 题意:求最大强连通分量的大小以及所包含的顶点有哪些 Tarjan算法 #include<iostream> #include<queue> #include< ...
- BZOJ3224普通平衡树——非旋转treap
题目: 此为平衡树系列第一道:普通平衡树您需要写一种数据结构,来维护一些数,其中需要提供以下操作:1. 插入x数2. 删除x数(若有多个相同的数,因只删除一个)3. 查询x数的排名(若有多个相同的数, ...
- [luogu3369]普通平衡树(treap模板)
解题关键:treap模板保存. #include<cstdio> #include<cstring> #include<algorithm> #include< ...
- Qt5_简易画板_详细注释
代码下载链接: http://pan.baidu.com/s/1hsc41Ek 密码: 5hdg 显示效果如下: 代码附有详细注释(代码如下) /*** * 先新建QMainWindow, 项目名称 ...
- BZOJ 1588: Treap 模板
1588: [HNOI2002]营业额统计 Time Limit: 5 Sec Memory Limit: 162 MBSubmit: 12171 Solved: 4352 Description ...
- 51nod 1126 求递推序列的第N项 思路:递推模拟,求循环节。详细注释
题目: 看起来比较难,范围10^9 O(n)都过不了,但是仅仅是看起来.(虽然我WA了7次 TLE了3次,被自己蠢哭) 我们观察到 0 <= f[i] <= 6 就简单了,就像小学初中学的 ...
- 一套强大的vim配置文件+详细注释
phpchina折腾王独家配置,灰常牛叉的一套vim配置,另附有详细注释,自己折腾vim的时候可以参照其中的大部分设置进行一些个性化定制."是否兼容VI,compatible为兼容,noco ...
- MFC的PNG贴图按钮类(详细注释)
MFC的PNG贴图按钮类(详细注释) (转载请注明出处) 作者:梦镜谷雨 萌新第二次写帖子,请多多包涵.末尾附上相应代码(PS公司繁体系统所以部分注释繁体请别介意). 因自带控件不美观,于是网上参考学 ...
- dedecms首页入口的详细注释
今天闲来无事,就拿来dede首页的文件给大家详细解释一遍,以便于新手学习,注释过程非常非常非常的详细,里面解释到dede表前缀#@__代替的原理.解释到dede很多自定义函数的具体位置和具体作用等等疑 ...
随机推荐
- handler更新ui线程的基本用法
1.因为费时操作要放子线程,更新UI要放UI线程(主线程),所以子线程和主线程通信,通信的话要用到handler这个东西. 这里讲的比较简单,举2个例子说明 2.使用post的是handler ,使用 ...
- HDU 多校对抗赛 D Distinct Values
Distinct Values Time Limit: 4000/2000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)T ...
- php 上传csv文件
php fgetcsv()函数 定义和用法 fgetcsv() 函数从文件指针中读入一行并解析 CSV 字段. 与 fgets() 类似,不同的是 fgetcsv() 解析读入的行并找出 CSV 格式 ...
- CSS三大特性(继承、优先级、层叠)之个人见解
首先声明一下CSS三大特性——继承.优先级和层叠.继承即子类元素继承父类的样式,比如font-size,font-weight等f开头的css样式以及text-align,text-indent等t开 ...
- 转载:Java中的String与常量池
转载自http://developer.51cto.com/art/201106/266454.htm.感觉总结的不错,自己收藏一下. string是java中的字符串.String类是不可变的,对S ...
- openlayers3中应用proj4js
要在openlayers3中应用proj4js,需要在html中引用proj4js,然后在引用所需要的projection的js定义,如 http://epsg.io/21781-1753.js 然后 ...
- 51nod 1254 最大子段和 V2 ——单调栈
N个整数组成的序列a[1],a[2],a[3],…,a[n],你可以对数组中的一对元素进行交换,并且交换后求a[1]至a[n]的最大子段和,所能得到的结果是所有交换中最大的.当所给的整数均为负数时和为 ...
- 《linux下进程的创建,执行,监控和终止》
<linux下进程的创建,执行,监控和终止> http://blog.csdn.net/miss_acha/article/details/43671047 http://blog.csd ...
- pool.map的第二个参数想传入多个咋整?
from functools import partial from multiprocessing import Pool as ThreadPool pageurls=[] if maxpage: ...
- Chrome扩展及应用开发
Chrome扩展及应用开发(电子书) http://www.ituring.com.cn/minibook/950 文档 官方 https://developer.chrome.com/extensi ...