2023大厂真题提交网址(含题解):
www.CodeFun2000.com(http://101.43.147.120/)
最近我们一直在将收集到的机试真题制作数据并搬运到自己的OJ上,供大家免费练习,体会真题难度。现在OJ已录入50+道2023年最新大厂真题,同时在不断的更新。同时,可以关注"塔子哥学算法"公众号获得每道题的题解。
一.前言
这个数据结构早有耳闻.只是一直没学.跟着AgOH学了一波.发现很简单.
二.原理
二叉搜索树之所以不够优秀,是因为存在一些数据能够将二叉搜索树退化成一条链.从而导致平方级的复杂度.那么对于这个缺陷,大佬们想出了很多方法去解决,衍生出了①替罪羊树②有旋/无旋Treap③splay.今天我入门学习的就是无旋treap.
Treap之所以能够克服二叉搜索树的缺陷,主要因为它以随机的方式构造二叉搜索树.使得毒瘤数据失效.具体就是将二叉堆和二叉搜索树结合起来.而无旋treap就不需要旋转操作.直接split+merge搞就可以了过程非常像玩拼图.
split有两种方式:按值分裂和按大小分裂.
1.将树分裂成两个部分,左部符合所有值小于等于val,右部符合所有值大于val.
2.将树分裂成两个部分,左部符合子树大小恰好等于val,右部符合大小为补集.
merge的过程很像线段树合并操作.
三.具体实现
说实话搞懂split操作和merge操作,基本就搞懂fhq-treap了.
大概结构:
1.每个节点需要存储:
struct Node
{
// 左右儿子,该点的值,该点的优先级,该子树大小.
int l , r , val , key , sz;
}fhq[maxn];
2.新建节点操作:
int newnode (int val){
fhq[++cnt].val = val;
fhq[cnt].key = rnd(); // 复杂度的保证
fhq[cnt].sz = 1;
return cnt;
}
3.在split/merge后更新节点信息:
void pushup (int x){
fhq[x].sz = fhq[fhq[x].l].sz + fhq[fhq[x].r].sz + 1;
}
4.分裂操作:
//注:当前节点在now,以 val为界限分成两部分.左边的父亲节点是x.右边的父亲节点是y.
void split (int now , int val , int &x , int &y)
{
if (!now){
x = y = 0;
return ;
}
// 代表根和左子树属于集合x.右子树尚未确定,需要继续抽离.
if (fhq[now].val <= val){
x = now;
split(fhq[now].r , val , fhq[now].r , y);
}else {
// 反之一样.
y = now;
split(fhq[now].l , val , x , fhq[now].l);
}
pushup(now);
}
5.合并操作:
//注:将子树x和子树y合并,返回根节点.
// 有个前提条件:子树x的值全严格小于子树y的值,这样才能保证它在合并后还是颗二叉搜索树.
int mer (int x , int y)
{
// 任意一个子树为空,返回另一个.两个都为空,返回空.
if (!x || !y) return x + y;
// 它同时又是一颗二叉堆,满足优先级特点.
if (fhq[x].key > fhq[y].key){
// x既要作为根,又因为前提,所以y要在x的右下方.
fhq[x].r = mer(fhq[x].r , y);
pushup(x);
return x;
}
// 反之一样.
fhq[y].l = mer(x , fhq[y].l);
pushup(y);
return y;
}
四.模板题目
4.1.洛谷P3369:普通平衡树
fhqTreap可以实现所有其他平衡树能实现的效果.
1.插入数
2.删除 x 数(若有多个相同的数,因只删除一个)
3.查询 x 数的排名(排名定义为比当前数小的数的个数 +1 )
4.查询排名为 x 的数
5.求 x 的前驱(前驱定义为小于 x,且最大的数)
6.求 x 的后继(后继定义为大于 x,且最小的数)
#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define pii pair<int,int>
#define pb push_back
#define mp make_pair
#define vi vector<int>
#define vll vector<ll>
#define fi first
#define se second
const int maxn = 1e6 + 5;
const int mod = 1e9 + 7;
struct Node
{
int l , r , val , key , sz;
}fhq[maxn];
int cnt , rt;
mt19937 rnd(233);
int newnode (int val){
fhq[++cnt].val = val;
fhq[cnt].key = rnd();
fhq[cnt].sz = 1;
return cnt;
}
void pushup (int x){
fhq[x].sz = fhq[fhq[x].l].sz + fhq[fhq[x].r].sz + 1;
}
<