一、Treap简介
Treap 是一种具有堆性质的二叉搜索树
原理:为每一个结点赋予一个随机值使其满足堆的性质,
保证树高度在O(logN)左右,以此保证较低的时间复杂度
Treap和set比较:
Treap比set更好实现
Treap更易于处理类似第K性质的求解问题,而set实现起来稍逊一筹
综上述,Treap常用于算法竞赛需要手写BST的时候,尤其是名次树
二、实现
#include<iostream>
#include<algorithm>
using namespace std;
const int maxNode = 1<<15;
const int INF = 0x3f3f3f3f;
class Treap
{
int root, treapCnt, key[maxNode], priority[maxNode], childs[maxNode][2], cnt[maxNode], size[maxNode];
int rand()
{
static int seed = 2333;
return seed = (int)((((seed ^ 998244353) + 19260817ll) * 19890604ll) % 1000000007);
}
//旋转
void rotate(int& x, int t)
{
int y = childs[x][t];
childs[x][t] = childs[y][1 - t];
childs[y][1 - t] = x;
update(x);
update(y);
x = y;
}
//更新规模大小
void update(const int x)
{
size[x] = size[childs[x][0]] + cnt[x] + size[childs[x][1]];
}
//插入k值
void _insert(int& x, const int k)
{
if (x)
{
if (key[x] == k)
{
cnt[x]++; //如果该键值存在,那么数量+1
}
else
{
bool t = key[x] < k; //判断k应属的子树
_insert(childs[x][t], k);
if (priority[childs[x][t]] < priority[x])
{
rotate(x, t);
}
}
}
else
{
x = treapCnt++;
key[x] = k;
cnt[x] = 1;
priority[x] = rand();
childs[x][0] = childs[x][1] = 0;
}
update(x);
}
void _erase(int& x, const int k)
{
if (key[x] == k)
{
if (cnt[x] > 1)
cnt[x]--;
else
{
if (childs[x][0] == 0 && childs[x][1] == 0)
{
x = 0;
return;
}
int t = priority[childs[x][0]] > priority[childs[x][1]];
rotate(x, t);
_erase(x, k);
}
}
else
{
_erase(childs[x][key[x] < k], k);
}
update(x);
}
int _getKth(int& x, int k, const bool ismax)
{
if (k <= size[childs[x][ismax]])
{
return _getKth(childs[x][ismax], k, ismax);
}
k -= size[childs[x][ismax]] + cnt[x];
if (k <= 0)
return key[x];
return _getKth(childs[x][!ismax], k, ismax);
}
int _findRank(const int p, const int x)
{
if (!p)return 0;
if (key[p] == x)return size[childs[p][0]] + 1;
if (x > key[p])return size[childs[p][0]] + cnt[p] + _findRank(childs[p][1], x);
else return _findRank(childs[p][0], x);
}
int _findBack(const int p, const int x)
{
if (!p)return -INF;
if (key[p] < x)return max(key[p], _findBack(childs[p][1], x));
else if (key[p] >= x)return _findBack(childs[p][0], x);
}
int _findFront(const int p, const int x)
{
if (!p)return INF;
if (key[p] <= x)return _findFront(childs[p][1], x);
else return min(key[p], _findFront(childs[p][0], x));
}
public:
Treap()
{
root = 0;
treapCnt = 1;
priority[0] = INF;
size[0] = 0;
}
//插入键值k
void insert(const int k)
{
_insert(root, k);
}
//删除键值k
void erase(const int k)
{
_erase(root, k);
}
//查询 K-th
int getKth(const int k, const bool ismax)
{
return _getKth(root, k, ismax);
}
//查询x的排名
int find_rank(const int x)
{
return _findRank(root, x);
}
//查询键值x的前驱
int find_back(const int x)
{
return _findBack(root, x);
}
//查询键值x的后继
int find_front(const int x)
{
return _findFront(root, x);
}
};