由于有相同的数,每个节点加一个权值表示此数出现的次数

 #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))的更多相关文章

  1. 洛谷.3369.[模板]普通平衡树(fhq Treap)

    题目链接 第一次(2017.12.24): #include<cstdio> #include<cctype> #include<algorithm> //#def ...

  2. 【洛谷P3369】普通平衡树——Splay学习笔记(一)

    二叉搜索树(二叉排序树) 概念:一棵树,若它的左子树不空,则左子树上所有结点的值均小于它的根结点的值: 若它的右子树不空,则右子树上所有结点的值均大于它的根结点的值: 它的左.右子树也分别为二叉搜索树 ...

  3. 洛谷.3369.[模板]普通平衡树(Splay)

    题目链接 第一次写(2017.11.7): #include<cstdio> #include<cctype> using namespace std; const int N ...

  4. 洛谷.3391.[模板]文艺平衡树(Splay)

    题目链接 //注意建树 #include<cstdio> #include<algorithm> const int N=1e5+5; //using std::swap; i ...

  5. 洛谷P3369 【模板】普通平衡树(Treap/SBT)

    洛谷P3369 [模板]普通平衡树(Treap/SBT) 平衡树,一种其妙的数据结构 题目传送门 题目描述 您需要写一种数据结构(可参考题目标题),来维护一些数,其中需要提供以下操作: 插入x数 删除 ...

  6. 【洛谷P3369】【模板】普通平衡树题解

    [洛谷P3369][模板]普通平衡树题解 题目链接 题意: 您需要写一种数据结构(可参考题目标题),来维护一些数,其中需要提供以下操作:1. 插入x数2. 删除x数(若有多个相同的数,因只删除一个)3 ...

  7. 洛谷P3369普通平衡树(Treap)

    题目传送门 转载自https://www.cnblogs.com/fengzhiyuan/articles/7994428.html,转载请注明出处 Treap 简介 Treap 是一种二叉查找树.它 ...

  8. 洛谷P3373 [模板]线段树 2(区间增减.乘 区间求和)

    To 洛谷.3373 [模板]线段树2 题目描述 如题,已知一个数列,你需要进行下面两种操作: 1.将某区间每一个数加上x 2.将某区间每一个数乘上x 3.求出某区间每一个数的和 输入输出格式 输入格 ...

  9. luoguP3369[模板]普通平衡树(Treap/SBT) 题解

    链接一下题目:luoguP3369[模板]普通平衡树(Treap/SBT) 平衡树解析 #include<iostream> #include<cstdlib> #includ ...

  10. (treap)[bzoj3224][洛谷3369][cogs1829]Tyvj 1728 普通平衡树

    Description 您需要写一种数据结构(可参考题目标题),来维护一些数,其中需要提供以下操作:1. 插入x数2. 删除x数(若有多个相同的数,因只删除一个)3. 查询x数的排名(若有多个相同的数 ...

随机推荐

  1. Ubuntu系统U盘安装以及降内核

    由于项目需要,要用U盘制作一个Linux系统,支持EFI启动,并且内核版本要求是2.6.35.6.所以在选系统的时候,就必须要选安装文件里面带有EF I目录,并且该目录下面有BOOTx64.EFI和g ...

  2. 【Nginx】惊群问题

    转自:江南烟雨 惊群问题的产生 在建立连接的时候,Nginx处于充分发挥多核CPU架构性能的考虑,使用了多个worker子进程监听相同端口的设计,这样多个子进程在accept建立新连接时会有争抢,这会 ...

  3. ThoughtWorks技术雷达

    ThoughtWorks技术雷达 技术成熟方案的一个推荐网站.

  4. 【原创】PHP扩展开发入门

    PHP扩展开发入门 作者:wf (360电商技术组) 在我们编写自己的第一个php扩展之前,先了解一下php的总体架构和执行机制. php的架构如图1所看到的. 当中一个重要的就是SAPI(serve ...

  5. Android使用am命令实现拨打电话、打开应用

    前提: 在Android 通话自己主动化測试中会用到am命令去拨打电话.打开音乐播放器播放音乐等等操作. 这里总结一下am命令. Android am命令: (1)命令參数: am start -n ...

  6. 在XX公司工作第二天,维护已有代码

    根据<C++ More Exception>所述的规则: Rule #1: Never write using-directives in header files. Rule #2: N ...

  7. Unity5的关卡切换

    本文章由cartzhang编写,转载请注明出处. 全部权利保留. 文章链接:http://blog.csdn.net/cartzhang/article/details/51055584 作者:car ...

  8. xcode7 怎样真机測试

    1. 下载xcode7 能够通过訪问 https://developer.apple.com/xcode/downloads/ 下载最新的xcode7的版本号 只是官网的下载速度太慢了,这个最好百度一 ...

  9. my-small.cnf my-medium.cnf my-large.cnf my-huge.cnf

    my-small.cnf my-medium.cnf my-large.cnf my-huge.cnf 是 MySQL 默认的几个配置文件.针对不同配置的服务器可以使用不同的配置文件,将你需要的那一个 ...

  10. react 中的 PureComponent

    React.PureComponent最重要的一个用处就是优化React应用,因为它减少了应用中的渲染次数,所以对性能的提升是非常可观的. 原理:在普通的 componnet 组件中,shouldCo ...