口胡

其实就是传说中的无旋treap。鉴于我总是写不出无旋treap,但是无旋treap又意外的好用,而且之前这个无旋treap板子是在远航大佬的博客上学的,但是远航貌似现在没时间维护博客,所以我就发一篇方便以后自己翻翻。其实远航大佬还是写的很好的,如果后续有维护的话建议看远航的文章入门。。

无旋treap好打,同样可以支持按权值维护或者维护序列,核心函数一般顶多四个,所以码量相比于splay确实会少很多,在一般需要支持一个比较简单的操作但set却不支持时,是一个很好的替代品。不信看下面普通平衡树的代码。

本质就是维护一个以rand为权的小根堆,由于rand是我们自己随机出来的,所以树高期望是O(log⁡n)O(\log n)O(logn)的。

合并

无论是维护权值还是序列,都通用一个合并函数,而这个函数其实是和可并堆相似的,由于x完全y左边,所以才可以做到O(log⁡n)O(\log n)O(logn)的合并。我直到今年暑假还一直误以为它可以O(log⁡n)O(\log n)O(logn)合并任意两棵按权值排的无旋treap。

int merge(int x,int y)
{if(!x||!y) return x+y;if(rnd[x]<rnd[y]){ch[x][1]=merge(ch[x][1],y);pushup(x);return x;}else{ch[y][0]=merge(x,ch[y][0]);pushup(y);return y;}
}

分裂

维护权值的分裂长这样,其中k的含义是把小于等于k的都放进x子树中,大于的则在y子树中。

void split(int now,int k,int &x,int &y)
{if(!now) x=y=0;else{if(val[now]<=k) x=now,split(ch[now][1],k,ch[now][1],y);else y=now,split(ch[now][0],k,x,ch[now][0]);pushup(now);}
}

而维护序列的长这样,k的含义是把前k个放进x子树中,其他放进y子树中。

void split(int now,int k,int &x,int &y)
{if(!now) x=y=0;else{if(k<=s[ch[now][0]]) y=now,split(ch[now][0],k,x,ch[now][0]);else x=now,split(ch[now][1],k-s[ch[now][0]]-1,ch[now][1],y);pushup(now);}
}

第k小

在找前驱/后继时,为了方便实现代码我们会需要这么一个函数。本质和splay的kth一致,就不再赘述。

int kth(int now,int k)
{while(1){if(k<=s[ch[now][0]]) now=ch[now][0];else{if(k==s[ch[now][0]]+1) return now;else k-=s[ch[now][0]]+1,now=ch[now][1];}}
}

其他操作

其他的很多操作可以自己yy的,通常的套路就是先split成两棵子树,然后再做操作,最后合并回来即可。

比如维护权值的时候插入一个x,那么就是按x分裂一下,在新增一个节点,再依次合并。

Code

普通平衡树的代码。

#include <cstdlib>
#include <cstdio>
#define rg register
#define pushup(x) s[x]=s[ch[x][0]]+s[ch[x][1]]+1
using namespace std;
typedef long long ll;
const int maxn=100010;
template <typename Tp> inline int getmin(Tp &x,Tp y){return y<x?x=y,1:0;}
template <typename Tp> inline int getmax(Tp &x,Tp y){return y>x?x=y,1:0;}
template <typename Tp> inline void read(Tp &x)
{x=0;int f=0;char ch=getchar();while(ch!='-'&&(ch<'0'||ch>'9')) ch=getchar();if(ch=='-') f=1,ch=getchar();while(ch>='0'&&ch<='9') x=x*10+ch-'0',ch=getchar();if(f) x=-x;
}
int m,sz,rt,op,a,x,y,z,val[maxn],rnd[maxn],s[maxn],ch[maxn][2];
int new_node(int x)
{s[++sz]=1;val[sz]=x;rnd[sz]=rand();return sz;
}
int merge(int x,int y)
{if(!x||!y) return x+y;if(rnd[x]<rnd[y]){ch[x][1]=merge(ch[x][1],y);pushup(x);return x;}else{ch[y][0]=merge(x,ch[y][0]);pushup(y);return y;}
}
void split(int now,int k,int &x,int &y)
{if(!now) x=y=0;else{if(val[now]<=k) x=now,split(ch[now][1],k,ch[now][1],y);else y=now,split(ch[now][0],k,x,ch[now][0]);pushup(now);}
}
int kth(int now,int k)
{while(1){if(k<=s[ch[now][0]]) now=ch[now][0];else{if(k==s[ch[now][0]]+1) return now;else k-=s[ch[now][0]]+1,now=ch[now][1];}}
}
int main()
{srand(19260817);read(m);while(m--){read(op);read(a);if(op==1){split(rt,a,x,y);rt=merge(merge(x,new_node(a)),y);}if(op==2){split(rt,a,x,z);split(x,a-1,x,y);y=merge(ch[y][0],ch[y][1]);rt=merge(merge(x,y),z);}if(op==3){split(rt,a-1,x,y);printf("%d\n",s[x]+1);rt=merge(x,y);}if(op==4) printf("%d\n",val[kth(rt,a)]);if(op==5){split(rt,a-1,x,y);printf("%d\n",val[kth(x,s[x])]);rt=merge(x,y);}if(op==6){split(rt,a,x,y);printf("%d\n",val[kth(y,1)]);rt=merge(x,y);}}return 0;
}

口胡fhq treap相关推荐

  1. FHQ Treap及其可持久化与朝鲜树式重构

    FHQ Treap,又称无旋treap,一种不基于旋转机制的平衡树,可支持所有有旋treap.splay等能支持的操作(只有在LCT中会比splay复杂度多一个log).最重要的是,它是OI中唯一一种 ...

  2. P2596 [ZJOI2006]书架(fhq treap)

    P2596 [ZJOI2006]书架 我们用fhq treap来完成这一题 对于一个新插入的节点我们取权值为其索引值,其所记录的valuevaluevalue是其当前索引所在位置. 操作一:把索引为v ...

  3. 二分图相关结论及口胡证明

    考虑点集A,B二分图 最小点覆盖: 概念:用最少的点覆盖二分图中所有边. 结论:最小覆盖点=最大匹配 证明:选择点集A所有匹配点,如果还存在一条边的两个端点都不在匹配点中那么让该两点匹配则最大匹配数目 ...

  4. 可持久化平衡树(FHQ Treap)

    两个最基本的操作 merge合并 split分割 merge 把两棵treap合并成一棵treap,要满足T1最大值要比T2最小值小,比较将随机数值key值更大的作为合并后的根 假设T1作为根节点作为 ...

  5. [2015国家集训队互测]口胡

    比赛链接 http://uoj.ac/contest/11 口胡题解 A.[集训队互测2015]Robot 直接果断打暴力了...这个暴力很好写,我就不废话了 B.[集训队互测2015]Marketi ...

  6. FHQ Treap 详解

    0. 简单介绍 FHQ Treap,以下简写为fhq,是一种treap(树堆)的变体,功能比treap强大,代码比splay好写,易于理解,常数稍大. fhq不需要通过一般平衡树的左右旋转来保持平衡, ...

  7. FHQ Treap 总结

    [前言(一堆废话)] 目前 OI 竞赛中两大主流平衡树之一就是 FHQ Treap(另一个是 Splay). 普通 BST 的中序遍历中,val 值构成一个单调递增的序列. Treap 在 BST 的 ...

  8. Treap + FHQ Treap

    一:Treap 支持:插入.删除.查询 x x x 的排名.查询排名为 x x x 的数.查前驱.查后继.左旋右旋 模板题:P3369 [模板]普通平衡树 #include<bits/stdc+ ...

  9. 平衡树学习笔记之 fhq Treap

    平衡树学习笔记 1:fhq Treap(非旋 Treap) 正文开始前首先 %%% fhq 大佬. 众所周知,平衡树是一种 非常猥琐 码量堪忧的数据结构. 他的祖先是一种叫做二叉搜索树 ( B S T ...

最新文章

  1. 【c语言】计算三角形面面积
  2. kafka与zookeeper关系
  3. c# DllImport 错误处理的不足及解决办法
  4. Socket连接的小知识,和一个疑难杂症
  5. android中TextView分段显示不同颜色,字体,时间
  6. 电脑技巧:Win10无线投屏功能介绍
  7. Java 8日期和时间
  8. Nginx 配置TCP负载均衡
  9. Git 仓库中文件名大小写问题
  10. android 360自动更新,解决Android百度自动更新SDK和360自动更新SDK兼容
  11. 云安全之虚拟机安全监控
  12. sql Server索引优化[转]
  13. 综合船桥系统电子海图数据库设计研究
  14. vue 按钮控制鼠标滚轮放大缩小
  15. AutoCAD2020安装教程
  16. 【ICPC-303】hau 1874 畅通工程续
  17. 查看电脑是否能插内存条
  18. [HITICS]大作业——程序人生Hello‘s P2P
  19. 人工智能 之 定义与发展
  20. 离群值(异常值)处理

热门文章

  1. 网站框架搭建——基于Django框架的天天生鲜电商网站项目系列博客(二)
  2. (通用实例)设圆的半径r=1.5,圆柱高h=3,求圆的周长、圆面积、圆球体积。用scanf输入数据,输出计算结果,取小数点后2位。
  3. 2021年春招小tip分享,java后端面试总结+心得分享+面经!
  4. 历届试题+九宫重排+java_蓝桥杯 历届试题 九宫重排 (bfs+康托展开去重优化)...
  5. ECOS 3.0 SDK USER GUIDE
  6. leetcode-365——水壶问题
  7. 智能烧水壶(WIFI版)05——水温调节和灯光提示功能实现篇
  8. java接口是干啥_浅谈Java接口
  9. 高新技术企业到底有什么好处?
  10. 计算机技术英语教学,计算机技术在英语教学中的应用