种下一棵树:有旋Treap
第一个平衡树板子,有旋Treap。用随机函数规定一个堆,维护点权的同时维护堆的性质,可以有效地避免退化成链。按我的理解,建立一棵二叉排序树,树的形态会和给出节点的顺序有关。按照出题人很机智定理,数据肯定不会太容易操作,这时候就需要我们自行调整“数据顺序”,平衡树应运而生。
这个板子涵盖的操作有左旋、右旋(维护堆性质)、添加节点、删除节点(建树相关)、查找第x个元素、查找元素排名、查找前驱、查找后继这8种操作。改变树本身的操作都是取地址传参的,询问操作则都是简单传参。原理不是太难理解,应用则看以后刷题了。
#include<iostream>
#include<cstdio>
#include<cstring>
#include<ctime>
#include<cstdlib>
using namespace std;
const int sj=;
int n,opt,g,jg,cs,size;
struct tree
{
int l,r,v,w,rnd,size;
}t[sj];
void update(int x)
{
t[x].size=t[t[x].l].size+t[t[x].r].size+t[x].w;
}
void lturn(int &x)
{
int tt=t[x].r;
t[x].r=t[tt].l;
t[tt].l=x;
t[tt].size=t[x].size;
update(x);
x=tt;
}
void rturn(int &x)
{
int tt=t[x].l;
t[x].l=t[tt].r;
t[tt].r=x;
t[tt].size=t[x].size;
update(x);
x=tt;
}
void cr(int &x,int y)
{
if(x==)
{
size++;
x=size;
t[x].size=t[x].w=;
t[x].v=y;
t[x].rnd=rand();
return;
}
t[x].size++;
if(t[x].v==y) t[x].w++;
else if(y>t[x].v)
{
cr(t[x].r,y);
if(t[t[x].r].rnd<t[x].rnd) lturn(x);
}
else
{
cr(t[x].l,y);
if(t[t[x].l].rnd<t[x].rnd) rturn(x);
}
}
void sc(int &k,int x)
{
if(k==) return;
if(t[k].v==x)
{
if(t[k].w>)
{
t[k].w--;
t[k].size--;
return;
}
if(t[k].l*t[k].r==) k=t[k].l+t[k].r;
else if(t[t[k].l].rnd<t[t[k].r].rnd)
rturn(k),sc(k,x);
else
lturn(k),sc(k,x);
}
else if(x>t[k].v)
t[k].size--,sc(t[k].r,x);
else
t[k].size--,sc(t[k].l,x);
}
int query_rank(int k,int x)
{
if(k==) return ;
if(t[k].v==x) return t[t[k].l].size+;
else if(x>t[k].v)
return t[t[k].l].size+t[k].w+query_rank(t[k].r,x);
else return query_rank(t[k].l,x);
}
int query_num(int k,int x)
{
if(k==) return ;
if(x<=t[t[k].l].size)
return query_num(t[k].l,x);
else if(x>t[t[k].l].size+t[k].w)
return query_num(t[k].r,x-t[t[k].l].size-t[k].w);
else return t[k].v;
}
void query_pre(int k,int x)
{
if(k==) return;
if(t[k].v<x)
jg=k,query_pre(t[k].r,x);
else query_pre(t[k].l,x);
}
void query_sub(int k,int x)
{
if(k==) return;
if(t[k].v>x)
jg=k,query_sub(t[k].l,x);
else query_sub(t[k].r,x);
}
int main()
{
//freopen("t.txt","r",stdin);
scanf("%d",&n);
for(int i=;i<=n;i++)
{
scanf("%d%d",&opt,&cs);
if(opt==)
cr(g,cs);
if(opt==)
sc(g,cs);
if(opt==)
printf("%d\n",query_rank(g,cs));
if(opt==)
printf("%d\n",query_num(g,cs));
if(opt==)
{
jg=;
query_pre(g,cs);
printf("%d\n",t[jg].v);
}
if(opt==)
{
jg=;
query_sub(g,cs);
printf("%d\n",t[jg].v);
}
}
//while(1);
return ;
}
种下一棵树:有旋Treap的更多相关文章
- 平衡树简单教程及模板(splay, 替罪羊树, 非旋treap)
原文链接https://www.cnblogs.com/zhouzhendong/p/Balanced-Binary-Tree.html 注意是简单教程,不是入门教程. splay 1. 旋转: 假设 ...
- 替罪羊树&&非旋treap
题解: 替罪羊树的模板和splay差距还是比较大的.. 按照我的splay的写法 真是都是问题.. 替罪羊树就是暴力的搞 当某颗子树大小大于这棵树的alpha时 就退出 另外删除的时候打懒标记删除 当 ...
- [转载]无旋treap:从好奇到入门(例题:bzoj3224 普通平衡树)
转载自ZZH大佬,原文:http://www.cnblogs.com/LadyLex/p/7182491.html 今天我们来学习一种新的数据结构:无旋treap.它和splay一样支持区间操作,和t ...
- [您有新的未分配科技点]无旋treap:从好奇到入门(例题:bzoj3224 普通平衡树)
今天我们来学习一种新的数据结构:无旋treap.它和splay一样支持区间操作,和treap一样简单易懂,同时还支持可持久化. 无旋treap的节点定义和treap一样,都要同时满足树性质和堆性质,我 ...
- 2017年陕西省网络空间安全技术大赛——种棵树吧——Writeup
2017年陕西省网络空间安全技术大赛——种棵树吧——Writeup 下载下来的zip解压得到两个jpg图片,在Kali中使用binwalk查看文件类型如下图: 有两个发现: 1111.jpg 隐藏了一 ...
- [模板] 平衡树: Splay, 非旋Treap, 替罪羊树
简介 二叉搜索树, 可以维护一个集合/序列, 同时维护节点的 \(size\), 因此可以支持 insert(v), delete(v), kth(p,k), rank(v)等操作. 另外, prev ...
- Trees in a Wood. UVA 10214 欧拉函数或者容斥定理 给定a,b求 |x|<=a, |y|<=b这个范围内的所有整点不包括原点都种一棵树。求出你站在原点向四周看到的树的数量/总的树的数量的值。
/** 题目:Trees in a Wood. UVA 10214 链接:https://vjudge.net/problem/UVA-10214 题意:给定a,b求 |x|<=a, |y|&l ...
- 非旋treap套线段树
BZOJ3065. 去年用pascal 块链过了.. 今年来试了试非旋treap大法 注定被块链完爆 代码留这. 第一份 :辣鸡的 垃圾回收做法 跑得极慢 #include <bits/ ...
- [转载]无旋treap:从单点到区间(例题 BZOJ1500&NOI2005 维护数列 )
转自ZZH大佬,原文:http://www.cnblogs.com/LadyLex/p/7182631.html 1500: [NOI2005]维修数列 Time Limit: 10 Sec Mem ...
随机推荐
- 简单总结下关于blob的图片上传
我是从一本书上看到了Azure Blob,然后在网上浪了一会儿,发现了这篇文章,里面他已经把重点的则重地方讲完了,"飞机票:http://www.cnblogs.com/sparkdev/p ...
- 基于Java SE的模拟双色球彩票系统
1.双色球规则: ①双色球分为红球和蓝球,红球选择的范围为1-33,而且红球选择6个数字:蓝球选择的范围为1-16,而且只能选择1个数字. ②选择方式为随机选择号码和手动输入选择号码. ③生成号码的顺 ...
- Vue和Bootstrap的整合之路
我是一个刚刚接触前端开发的新手,所以有必要记录如何将Bootstrap和Vue进行整合. 如果你是老手,请直接绕道而过.作为一个新手,里面的步骤,过程或者专业术语未必正确,如果你发现哪里错误了,请发邮 ...
- 【LeetCode】225. Implement Stack using Queues
题目: Implement the following operations of a stack using queues. push(x) -- Push element x onto stack ...
- 如何为一个eclipse安装android环境
据说android已经不再支持android adt-bundle的开发环境了,所以如果继续使用的话,会不再更新 使用eclipse来安装android环境或者使用android studio 但是以 ...
- SharePoint 2016 修改左上角连接
SharePoint 2016默认会有左上角这样的一个功能. 估计都想把它改掉. 方法1: 打开,输入下面的命令,可将图中的sharepoint修改为想要的文字 $webapp = Get-SPWe ...
- c++ new delete 常踩的坑
WeTest 导读 c++ 是公司开发最常用的语言之一, 那New和Delete 这两个函数是所有开发者即爱又恨的函数.由new 和delete引发的bug , coredump , 让多少程序员加了 ...
- JSON.parse()与JSON.stringify()的区别
JSON.parse()[从一个字符串中解析出json对象] 例子: //定义一个字符串 var data='{"name":"goatling"}' //解析 ...
- 进击的AssetBundles和它的工具们
0x00 前言 周末的时候在家看了下去年的Unite16 LA的视频.其中一个session很有趣,是AssetBundles开发团队Reichert的一个"总结过往,畅想未来"的 ...
- Chrome浏览器扩展开发系列之二:Google Chrome浏览器扩展的调试
1) 查看扩展程序的详细信息和ID 通过Chrome 浏览器的“ 工具->更多工具->扩展程序”,打开chrome://extensions页面,选中右上角的“开发者模式”,可以 ...