http://www.lydsy.com/JudgeOnline/problem.php?id=3224

经典的平衡树模板题…各种平衡树好像都可以(黄学长之前好像还用vector卡过了这题)

所以这篇博客也就来存一下模板什么的…

如果发现有什么地方讲错的还请留言怼我


1.Treap

首先是经典的Treap:Treap=Tree+heap

这里每个结点有两个值$v$(结点的值)和$rnd$(一个随机值),叫Treap的原因也就是它遵循二叉查找树的性质($o$的左子树的$v$<$o$的$v$<$o$右子树的$v$)和堆的性质($o$左子树的$rnd$>$o$的$rnd$且$o$右子树的$rnd$>$o$的$rnd$,当然改成<也可以,不过这里我统一用>方便说)

二叉查找树的性质在插入的时候直接维护:如果要插入的比当前小就丢给左孩子,大的话就丢给右孩子(相等的话就直接存这个点上,这里用一个变量$w$来记录这个点实际上有几个点)

堆的性质通过旋转操作来维护:

比如如果你发现$o$的左孩子的$rnd$比$o$的$rnd$小了,它应该比较大才对,那这时候就可以把$o$右旋让它的左孩子变成它的父亲,可以发现这样子做二叉搜索树的性质并没有被破坏,如果是右孩子$rnd$比$o$大的话同理就用左旋啦,靠这两个操作就完成了堆性质的维护。因为用的是随机数所以期望情况下效率还是不错的。

(建议配合图片食用)

其他操作都比较简单了…具体还是见代码吧

#include<cstdio>
#include<cstdlib>
#define rep(i,n) for(register int i=1;i<=n;i++)
using namespace std;
inline int read()
{
int s=0,f=1;char c=getchar();
while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();}
while(c>='0'&&c<='9'){s=s*10+c-'0';c=getchar();}
return s*f;
}
const int N=100005;
struct tree
{
int s,w,rnd,l,r,v;
}tr[N];
int n,rot,cnt,op;
inline void updata(int x)
{
tr[x].s=tr[tr[x].l].s+tr[tr[x].r].s+tr[x].w;
}
inline void rturn(int &x)
{
int t=tr[x].l;tr[x].l=tr[t].r;tr[t].r=x;
tr[t].s=tr[x].s;updata(x);x=t;
}
inline void lturn(int &x)
{
int t=tr[x].r;tr[x].r=tr[t].l;tr[t].l=x;
tr[t].s=tr[x].s;updata(x);x=t;
}
inline void insert(int &k,int val)
{
if(k==0)
{
k=++cnt;tr[k].v=val;tr[k].w=tr[k].s=1;
tr[k].rnd=rand();return;
}
tr[k].s++;
if(tr[k].v==val)
tr[k].w++;
else if(tr[k].v<val)
{
insert(tr[k].r,val);
if(tr[tr[k].r].rnd<tr[k].rnd)lturn(k);
}else
{
insert(tr[k].l,val);
if(tr[tr[k].l].rnd<tr[k].rnd)rturn(k);
}
}
inline void del(int &k,int val)
{
if(k==0)return;
if(tr[k].v==val)
{
if(tr[k].w>1)
tr[k].w--,tr[k].s--;
else
{
if(tr[k].l*tr[k].r==0)
k=tr[k].l+tr[k].r;
else if(tr[tr[k].l].rnd<tr[tr[k].r].rnd)
rturn(k),del(k,val);
else
lturn(k),del(k,val);
}
}else if(tr[k].v<val)
{
tr[k].s--;
del(tr[k].r,val);
}else
{
tr[k].s--;
del(tr[k].l,val);
}
}
inline int query_number_rank(int k,int val)
{
if(k==0)return 0;
if(tr[k].v==val)
return tr[tr[k].l].s+1;
else if(tr[k].v<val)
return query_number_rank(tr[k].r,val)+tr[tr[k].l].s+tr[k].w;
else
return query_number_rank(tr[k].l,val);
}
inline void query_rank(int k,int x,int &ans)
{
if(k==0)return;
if(x<=tr[tr[k].l].s)
query_rank(tr[k].l,x,ans);
else if(tr[tr[k].l].s+tr[k].w<x)
query_rank(tr[k].r,x-tr[tr[k].l].s-tr[k].w,ans);
else ans=tr[k].v;
}
inline void query_pre(int k,int x,int &ans)
{
if(k==0)return;
if(tr[k].v<x)
{
ans=tr[k].v;
query_pre(tr[k].r,x,ans);
}else
query_pre(tr[k].l,x,ans);
}
inline void query_sub(int k,int x,int &ans)
{
if(k==0)return;
if(tr[k].v>x)
{
ans=tr[k].v;
query_sub(tr[k].l,x,ans);
}else
query_sub(tr[k].r,x,ans);
}
int main()
{
srand(19260817);
n=read();
rep(i,n)
{
int x,ans=0;
op=read();x=read();
if(op==1)
insert(rot,x);
else if(op==2)
del(rot,x);
else if(op==3)
printf("%d\n",query_number_rank(rot,x));
else if(op==4)
{
query_rank(rot,x,ans);
printf("%d\n",ans);
}else if(op==5)
{
query_pre(rot,x,ans);
printf("%d\n",ans);
}else
{
query_sub(rot,x,ans);
printf("%d\n",ans);
}
}
return 0;
}

2.01Trie

别人博客的:http://www.cnblogs.com/KingSann/articles/7339563.html

有个神奇的东西叫01Trie…其实就是一颗字符集为$\{0,1 \}$的Trie。

然后我们把要存的变量搞成二进制丢到这颗Trie里面就行了!非常好写。

缺点就是就是空间比较大,以及如果要存浮点数就有点无能为力了…(能不能写成$a*10^b$的形式丢树上呢…脑补ing…)

#include<cstdio>
const int N=100005*33;
const int T=(int)1e7;//偏移的大小
const int B=31;
inline int read()
{
int s=0,f=1;char c=getchar();
while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();}
while(c>='0'&&c<='9'){s=s*10+c-'0';c=getchar();}
return s*f;
}
int n,cnt=1,x,op;
int tr[N][2],f[N];
inline void insert(int val,int c)
{
int k=1;val+=T;
for(register int i=B;~i;i--)
{
int t=(val>>i)&1;
if(!tr[k][t])tr[k][t]=++cnt;
k=tr[k][t];f[k]+=c;
}
}
inline int rank(int val)
{
int k=1,res=0;val+=T;
for(register int i=B;~i;i--)
{
int t=(val>>i)&1;
if(t)res+=f[tr[k][0]];
k=tr[k][t];
}
return res;
}
inline int kth(int val)
{
int k=1,res=0;
for(register int i=B;~i;i--)
{
if(val>f[tr[k][0]])res|=(1<<i),val-=f[tr[k][0]],k=tr[k][1];
else k=tr[k][0];
}
res-=T;return res;
}
int main()
{
n=read();
while(n--)
{
op=read();x=read();
if(op==1)insert(x,1);
else if(op==2)insert(x,-1);
else if(op==3)printf("%d\n",rank(x)+1);
else if(op==4)printf("%d\n",kth(x));
else if(op==5)printf("%d\n",kth(rank(x)));
else if(op==6)printf("%d\n",kth(rank(x+1)+1));
}
return 0;
}

先写到这了其他的有空再更…

[日常摸鱼]bzoj3224普通平衡树-Treap、Splay、01Trie、替罪羊树…的更多相关文章

  1. 简析平衡树(一)——替罪羊树 Scapegoat Tree

    前言 平衡树在我的心目中,一直都是一个很高深莫测的数据结构.不过,由于最近做的题目的题解中经常出现"平衡树"这三个字,我决定从最简单的替罪羊树开始,好好学习平衡树. 简介 替罪羊树 ...

  2. BZOJ 3224 - 普通平衡树 - [Treap][Splay]

    题目链接:https://www.lydsy.com/JudgeOnline/problem.php?id=3224 Description 您需要写一种数据结构(可参考题目标题),来维护一些数,其中 ...

  3. [洛谷P3369] 普通平衡树 Treap & Splay

    这个就是存一下板子...... 题目传送门 Treap的实现应该是比较正经的. 插入删除前驱后继排名什么的都是平衡树的基本操作. #include<cstdio> #include< ...

  4. BZOJ3224普通平衡树【Splay】

    3224: Tyvj 1728 普通平衡树 Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 11751  Solved: 5013 Descriptio ...

  5. [日常摸鱼]Luogu1801 黑匣子(NOI导刊)

    题意:写一个数据结构,要求滋兹两种操作,ADD:插入一个数,GET:令$i++$然后输出第$i$小的数 这个数据结构当然是平衡树啦!(雾) 写个Treap直接过掉啦- #include<cstd ...

  6. [bzoj3224]普通平衡树[Treap]

    Treap 的各种操作,模板题,要再写几遍 #include <iostream> #include <algorithm> #include <cstdio> # ...

  7. Hash 日常摸鱼笔记

    本篇文章是Hash在信息学竞赛中的应用的学习笔记,分多次更新(已经有很多坑了) 一维递推 首先是Rabin-Karp,对于一个长度为\(m\)的串\(S\) \(f(S)=\sum_{i=1}^{m} ...

  8. [日常摸鱼]HDU1724 Ellipse-自适应Simpson法

    模板题~ QAQ话说Simpson法的原理我还是不太懂-如果有懂的dalao麻烦告诉我~ 题意:每次给一个椭圆的标准方程,求夹在直线$x=l$和$x=r$之间的面积 Simpson法 (好像有时候也被 ...

  9. [日常摸鱼]bzoj1257余数之和

    题意:输入$k,n$,求$\sum_{i=1}^n k \mod i$ $k \mod i=k-i*\lfloor \frac{k}{i} \rfloor $,$n$个$k$直接求和,后面那个东西像比 ...

随机推荐

  1. 如何在苹果电脑下载器Folx中管理下载列表

    Folx是一款Mas OS专用的下载器,提供了便捷的下载管理.灵活的设置.今天小编准备跟大家聊一聊关于Folx中常见的几种下载管理方式. 一.管理任务状态栏 在Folx下载面板上,可以通过类别查看任务 ...

  2. 「CF645E」 Intellectual Inquiry

    题目链接 CF645E 题意 有一个长为\(n\)的由小写字母组成的字符串,需要用小写字母再填\(m\)位,使最后的字符串中本质不同的子串数量尽量多,答案对\(10^9+7\)取模. 本题数据:\(n ...

  3. 基于Koa2+mongoDB的后端博客框架

    主要框架:koa2全家桶+mongoose+pm2. 在阅读前建议将项目克隆到本地配合食用,否则将看得云里雾里. 项目地址:https://github.com/YogurtQ/koa-server. ...

  4. jmeter录制请求

    用了一段时间的jmeter感觉比LR方便很多,界面也比较简洁,开源免费,配置环境也方便,LR简直没法比,但唯一的是功能没有LR强大,毕竟是免费的,要求别那么高. 下面开始进入正题,配置环境和下载就不多 ...

  5. mysql-查询不同列的数量合计

    车辆违规信息表testmodel_test 表结构: 表字段:cra_id(车牌号),if_weigui(该次行驶是否违规,0是正常,1是违规) 目的: 查询表中共有几辆车,违规的有几辆车: 方法1 ...

  6. 【树形dp】【CF161D】distance on a tree + 【P1352】没有上司的舞会

    T1题面: 输入点数为N一棵树 求树上长度恰好为K的路径个数 (n < 1e5, k < 500) 这是今天的考试题,也是一道假的紫题,因为我一个根本不会dp的蒟蒻只知道状态就一遍A掉了- ...

  7. Java基础教程——类和对象

    视屏讲解:https://www.bilibili.com/video/av48272174 面向过程 VS 面向对象 面向过程:强调步骤. 面向对象:强调对象. 面向对象的特点就是:隐藏具体实现的细 ...

  8. 【mq读书笔记】如何保证三个消息文件的最终一致性。

    考虑转发任务未成功执行,此时消息服务器Broker宕机,导致commitlog,consumeQueue,IndexFile文件数据不一致. commitlog,consumeQueue遍历每一条消息 ...

  9. VUE:data数据中,能被网页渲染出来的数据类型有哪些

    我们都知道vue中,data里面的数据类型可以使任意类型. 但是能在网页上可以渲染出来的类型有哪些呢? 我们来看一下在VUE中data里的什么数据类型可以渲染出来. 我在下面列举了这些数据类型 显示结 ...

  10. LeetCode 025 Reverse Nodes in k-Group

    题目描述:Reverse Nodes in k-Group Given a linked list, reverse the nodes of a linked list k at a time an ...