treap板子(洛谷 P3369 【模板】普通平衡树(Treap/SBT))
由于有相同的数,每个节点加一个权值表示此数出现的次数
#include<cstdio>
#include<cstdlib>
#include<ctime>
#include<algorithm>
using namespace std;
#define MAXI 2147483647
//http://blog.csdn.net/h348592532/article/details/52837228随机数
int rand1()
{
static int x=;
return x=(48271LL*x+)%;
}
struct Node
{
Node* ch[];
int r;//优先级
int v;//value
int size;//维护子树的节点个数
int num;//当前数字出现次数
int cmp(int x) const//要在当前节点的哪个子树去查找,0左1右
{
if(x==v) return -;
return v<x;//x<v?0:1
}
void upd()
{
size=num;
if(ch[]!=NULL) size+=ch[]->size;
if(ch[]!=NULL) size+=ch[]->size;
}
}nodes[];
int mem,n;
Node* root=NULL;
void rotate(Node* &o,int d)
{
Node* t=o->ch[d^];o->ch[d^]=t->ch[d];t->ch[d]=o;
o->upd();t->upd();//o是t子节点,一定要这个顺序upd
o=t;//将当前节点变成旋转完后新的父节点
}
Node* getnode()
{
return &nodes[mem++];
}
void insert(Node* &o,int x)
{
if(o==NULL)
{
o=getnode();o->ch[]=o->ch[]=NULL;
o->v=x;o->r=rand1();o->num=;
}
else
{
if(o->v==x) ++(o->num);
else
{
int d=o->v < x;//x < o->v?0:1
insert(o->ch[d],x);
if(o->r < o->ch[d]->r) rotate(o,d^);//不是 x < o->ch[d]->r
}
}
o->upd();
}
void remove(Node* &o,int x)
{
int d=o->cmp(x);
if(d==-)
{
if(o->num > )
{
--(o->num);
}
if(o->num == )
{
if(o->ch[]==NULL) o=o->ch[];
else if(o->ch[]==NULL) o=o->ch[];
else
{
//int d2= o->ch[0]->r > o->ch[1]->r;//o->ch[0]->r > o->ch[1]->r ? 1:0
int d2=o->ch[]->r < o->ch[]->r;//o->ch[1]->r <= o->ch[0]->r
rotate(o,d2);
remove(o->ch[d2],x);
//左旋则原节点变为新节点的左子节点,右旋相反
}
}
}
else remove(o->ch[d],x);
if(o!=NULL) o->upd();
}
bool find(Node* o,int x)
{
int d;
while(o!=NULL)
{
d=o->cmp(x);
if(d==-) return ;
else o=o->ch[d];
}
return ;
}
int kth(Node* o,int k)
{
if(o==NULL||k<=||k > o->size) return ;
int s= o->ch[]==NULL ? : o->ch[]->size;
if(k>s&&k<=s+ o->num) return o->v;
else if(k<=s) return kth(o->ch[],k);
else return kth(o->ch[],k-s- o->num);
}
int rk(Node* o,int x)
{
int r=o->ch[]==NULL ? : o->ch[]->size;
if(x==o->v) return r+;
else if(x<o->v) return rk(o->ch[],x);
else return r+ o->num +rk(o->ch[],x);
}
int pre(Node* o,int x)
{
if(o==NULL) return -MAXI;
int d=o->cmp(x);
if(d<=) return pre(o->ch[],x);
else return max(o->v,pre(o->ch[],x));
}
int nxt(Node* o,int x)
{
if(o==NULL) return MAXI;
int d=o->cmp(x);
if(d!=) return nxt(o->ch[],x);
else return min(o->v,nxt(o->ch[],x));
}
int main()
{
int i,o,x;
scanf("%d",&n);
for(i=;i<=n;i++)
{
scanf("%d%d",&o,&x);
if(o==) insert(root,x);
else if(o==) remove(root,x);
else if(o==) printf("%d\n",rk(root,x));
else if(o==) printf("%d\n",kth(root,x));
else if(o==) printf("%d\n",pre(root,x));
else printf("%d\n",nxt(root,x));
}
return ;
}
本来想写成相同的数分成多个节点放的,写了一会儿各种细节,炸了
#include<cstdio>
#include<cstdlib>
#include<ctime>
#include<algorithm>
using namespace std;
struct Node
{
Node* ch[];
int r;//优先级
int v;//value
int size;//维护子树的节点个数 int cmp(int x) const//要在当前节点的哪个子树去查找,0左1右
{
if(x==v) return -;
return v<x;//x<v?0:1
}
void upd()
{
size=;
if(ch[]!=NULL) size+=ch[]->size;
if(ch[]!=NULL) size+=ch[]->size;
}
}nodes[];
int mem;
void rotate(Node* &o,int d)
{
Node* t=o->ch[d^];o->ch[d^]=t->ch[d];t->ch[d]=o;
o->upd();t->upd();
o=t;//将当前节点变成旋转完后新的父节点
}
Node* getnode()
{
return &nodes[mem++];
}
void insert(Node* &o,int x)
{
if(o==NULL)
{
o=getnode();o->ch[]=o->ch[]=NULL;
o->v=x;o->r=rand();
}
else
{
//int d=o->cmp(x);不重复
int d=o->v <= x;//x < o->v?0:1
//按照以上左侧的插入方式,相等的会在左子树中插入
insert(o->ch[d],x);
if(o->ch[d]->r > o->r)//不是> x
rotate(o,d^);
}
o->upd();
}
void remove(Node* &o,int x)
{
int d=o->cmp(x);
if(d==-)
{
if(o->ch[]==NULL) o=o->ch[];
else if(o->ch[]==NULL) o=o->ch[];
else
{
//int d2= o->ch[0]->r > o->ch[1]->r;//o->ch[0]->r > o->ch[1]->r ? 1:0
int d2=o->ch[]->r <= o->ch[]->r;
rotate(o,d2);
remove(o->ch[d2],x);
//左旋则原节点变为新节点的左子节点,右旋相反
}
}
else remove(o->ch[d],x);
if(o!=NULL) o->upd();
}
bool find(Node* o,int x)
{
int d;
while(o!=NULL)
{
d=o->cmp(x);
if(d==-) return ;
else o=o->ch[d];
}
return ;
}
int kth(Node* o,int k)
{
if(o==NULL||k<=||k > o->size) return ;
int s= o->ch[]==NULL ? : o->ch[]->size;
if(k==s+) return o->v;
else if(k<=s) return kth(o->ch[],k);
else return kth(o->ch[],k-s-);
}
//int rank(Node* o,int x)//不可重复
//{
// int r= t->ch[0]==NULL ? 0 : t->ch[0]->size;
// if(x==o->v) return r+1;
// else if(x<o->v) return rank(o->ch[0],x);
// else return r+1+rank(o->ch[1],x);
//}
int rank(Node* o,int x)//支持重复
{
int r=t->ch[]==NULL ? : t->ch[]->size;
if(x==o->v)
{
int t=rank(o->ch[
}
}
int pre(Node* o,int x)
{
if(o==NULL) return -;
if(x==o->v) return
if(x<o->v) return min(o->v,pre(o->ch[],
}
int main()
{
srand(time()); return ;
}
treap板子(洛谷 P3369 【模板】普通平衡树(Treap/SBT))的更多相关文章
- 洛谷.3369.[模板]普通平衡树(fhq Treap)
题目链接 第一次(2017.12.24): #include<cstdio> #include<cctype> #include<algorithm> //#def ...
- 【洛谷P3369】普通平衡树——Splay学习笔记(一)
二叉搜索树(二叉排序树) 概念:一棵树,若它的左子树不空,则左子树上所有结点的值均小于它的根结点的值: 若它的右子树不空,则右子树上所有结点的值均大于它的根结点的值: 它的左.右子树也分别为二叉搜索树 ...
- 洛谷.3369.[模板]普通平衡树(Splay)
题目链接 第一次写(2017.11.7): #include<cstdio> #include<cctype> using namespace std; const int N ...
- 洛谷.3391.[模板]文艺平衡树(Splay)
题目链接 //注意建树 #include<cstdio> #include<algorithm> const int N=1e5+5; //using std::swap; i ...
- 洛谷P3369 【模板】普通平衡树(Treap/SBT)
洛谷P3369 [模板]普通平衡树(Treap/SBT) 平衡树,一种其妙的数据结构 题目传送门 题目描述 您需要写一种数据结构(可参考题目标题),来维护一些数,其中需要提供以下操作: 插入x数 删除 ...
- 【洛谷P3369】【模板】普通平衡树题解
[洛谷P3369][模板]普通平衡树题解 题目链接 题意: 您需要写一种数据结构(可参考题目标题),来维护一些数,其中需要提供以下操作:1. 插入x数2. 删除x数(若有多个相同的数,因只删除一个)3 ...
- 洛谷P3369普通平衡树(Treap)
题目传送门 转载自https://www.cnblogs.com/fengzhiyuan/articles/7994428.html,转载请注明出处 Treap 简介 Treap 是一种二叉查找树.它 ...
- 洛谷P3373 [模板]线段树 2(区间增减.乘 区间求和)
To 洛谷.3373 [模板]线段树2 题目描述 如题,已知一个数列,你需要进行下面两种操作: 1.将某区间每一个数加上x 2.将某区间每一个数乘上x 3.求出某区间每一个数的和 输入输出格式 输入格 ...
- luoguP3369[模板]普通平衡树(Treap/SBT) 题解
链接一下题目:luoguP3369[模板]普通平衡树(Treap/SBT) 平衡树解析 #include<iostream> #include<cstdlib> #includ ...
- (treap)[bzoj3224][洛谷3369][cogs1829]Tyvj 1728 普通平衡树
Description 您需要写一种数据结构(可参考题目标题),来维护一些数,其中需要提供以下操作:1. 插入x数2. 删除x数(若有多个相同的数,因只删除一个)3. 查询x数的排名(若有多个相同的数 ...
随机推荐
- ios UITableView 获取点击cell对象
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath { UITabl ...
- 随机森林、gbdt算法
http://blog.csdn.net/songzitea/article/details/10035757 http://blog.csdn.net/holybin/article/details ...
- 【Nginx】Nginx基础架构
调用HTTP模块的流程: Worker进程会在一个for循环语句中反复调用事件模块检测网络事件.当事件模块检测到某个客户端发起的TCP请求时(接收到SYN包),将会为它建立TCP连接,成功建立连接后根 ...
- mtk刷机错误汇总
MTK常见错误解读与解决方法: 1.刷机过了红条,到了紫色条卡住.(错误代码4008) 解决方法:这种情况出现的话,大家可以把电池拿下来,然后重新安装上,进入REC后选择关机.然后重新刷. 2.驱动安 ...
- 3.将maven项目jar纳入maven仓库,Mave项目依赖另外一个Maven项目的案例
1 若想让maven项目依赖另外一个maven项目.被依赖的项目要在maven仓库中有对应的jar包,所以要对依赖的项目运行mvninstall命令. 2 新建第二个项目模块HelloFrien ...
- 关于disable和readonly
我们在做网页时,难免的会因为权限或者各种原因,想让使用者看到,但是却不想让用户去对值进行更改,我们有两个选择 一.我们使用disabled将文本框禁用掉. 二.我们使用readonly使得文本框只能读 ...
- c# 自定义Base16编码解码
一.自定义Base16编码原理 Base16编码跟Base64编码原理上有点不同,当然前面转换是一样的,都是是将输入的字符串根据默认编码转换成一 ...
- SLF4J: Failed to load class的问题及解决
今天在做接口测试,一运行测试程序,就跳出这样一个大大的错误: SLF4J: Failed to load class “org.slf4j.impl.StaticLoggerBinder”. SLF4 ...
- C++语言笔记系列之二十——模版
1.随意输入两个数x和y,输出最大值max. int max(int x, int y) {return x>y? x:y;} 2.函数模版 (1)用一种或者多种通用类型去表示函数--函数模版. ...
- Openstack-Ceilometer-获取主机内存 的使用
1. 物理server配置 1.1安装 參考 http://blog.csdn.net/qq_21398167/article/details/47019751 1.2 配置 关闭selin ...