fhq-treap 模板
各类函数
1. 定义 \(fhq-treap\)
struct Tree
{
int s[2]; // 左右孩子,s[0]表示左孩子,s[1]表示右孩子
int v; // 节点权值
int size; // 以i为根的子树的大小(包括根自己)
int dat; // 节点优先级
int rev; // 懒标记
}tr[N];
2. 用左右儿子信息更新父亲信息 \(pushup\)
void pushup(int u)
{
tr[u].size = tr[tr[u].s[0]].size + tr[tr[u].s[1]].size + 1;
}
3. 下传懒标记 \(pushdown\)
void pushdown(int u)
{
if (tr[u].rev)
{
swap(tr[u].s[0], tr[u].s[1]);
tr[tr[u].s[0]].rev ^= 1, tr[tr[u].s[1]].rev ^= 1;
tr[u].rev = 0;
}
}
4. 新开节点 \(init\)
int init(int v)
{
idx ++ ;
tr[idx].size = 1, tr[idx].v = v, tr[idx].dat = rand();
return idx;
}
5. 分裂\(fhq-treap\) (\(split\)
1.按权值分裂
void split(int u, int v, int &x, int &y)
{
if (!u) x = y = 0;
else
{
if (tr[u].v <= v) x = u, split(tr[u].s[1], v, tr[u].s[1], y);
else y = u, split(tr[u].s[0], v, x, tr[u].s[0]);
pushup(u);
}
}
- 按节点键值分裂
void split(int u, int v, int &x, int &y)
{
if (!u) x = y = 0;
else
{
pushdown(u);
if (tr[tr[u].s[0]].size + 1 <= v) x = u, split(tr[u].s[1], v - tr[tr[u].s[0]].size - 1, tr[u].s[1], y);
else y = u, split(tr[u].s[0], v, x, tr[u].s[0]);
pushup(u);
}
}
6. 合并两个 \(treap\) \(merge\)
int merge(int a, int b)
{
if (!a || !b) return a + b;
if (tr[a].dat < tr[b].dat)
{
pushdown(a);
tr[a].s[1] = merge(tr[a].s[1], b);
pushup(a);
return a;
}
else
{
pushdown(b);
tr[b].s[0] = merge(a, tr[b].s[0]);
pushup(b);
return b;
}
}
7. 插入一个数 \(insert\)
void insert(int v)
{
split(root, v, x, y);
root = merge(merge(x, init(v)), y);
}
8. 删除一个数 \(remove\)
void remove(int v)
{
split(root, v, x, z);
split(x, v - 1, x, y);
y = merge(tr[y].s[0], tr[y].s[1]);
root = merge(merge(x, y), z);
}
9. 查询排名 \(get_rank\)
int get_rank(int v)
{
split(root, v - 1, x, y);
int res = tr[x].size + 1;
root = merge(x, y);
return res;
}
10. 查询排名为\(k\)的数的权值 \(get_val\)
int get_val(int u, int k)
{
while (true)
{
if (tr[tr[u].s[0]].size >= k) u = tr[u].s[0];
else if (tr[tr[u].s[0]].size + 1 == k) return tr[u].v;
else k -= tr[tr[u].s[0]].size + 1, u = tr[u].s[1];
}
return -1;
}
11. 找前驱 \(get_pre\)
int get_pre(int v)
{
split(root, v - 1, x, y);
int res = get_val(x, tr[x].size);
root = merge(x, y);
return res;
}
12. 找后继 \(get_next\)
int get_next(int v)
{
split(root, v, x, y);
int res = get_val(y, 1);
root = merge(x, y);
return res;
}
模板题
1. 普通平衡树
#include <iostream>
#include <cstring>
#include <cstdio>
#include <algorithm>
using namespace std;
const int N = 100010;
int x, y, z;
int n;
int root, idx;
struct Tree
{
int s[2], v, size, dat;
}tr[N];
void pushup(int u)
{
tr[u].size = tr[tr[u].s[0]].size + tr[tr[u].s[1]].size + 1;
}
int init(int v)
{
idx ++ ;
tr[idx].size = 1, tr[idx].v = v, tr[idx].dat = rand();
return idx;
}
void split(int u, int v, int &x, int &y)
{
if (!u) x = y = 0;
else
{
if (tr[u].v <= v) x = u, split(tr[u].s[1], v, tr[u].s[1], y);
else y = u, split(tr[u].s[0], v, x, tr[u].s[0]);
pushup(u);
}
}
int merge(int a, int b)
{
if (!a || !b) return a + b;
if (tr[a].dat < tr[b].dat)
{
tr[a].s[1] = merge(tr[a].s[1], b);
pushup(a);
return a;
}
else
{
tr[b].s[0] = merge(a, tr[b].s[0]);
pushup(b);
return b;
}
}
void insert(int v)
{
split(root, v, x, y);
root = merge(merge(x, init(v)), y);
}
void remove(int v)
{
split(root, v, x, z);
split(x, v - 1, x, y);
y = merge(tr[y].s[0], tr[y].s[1]);
root = merge(merge(x, y), z);
}
int get_rank(int v)
{
split(root, v - 1, x, y);
int res = tr[x].size + 1;
root = merge(x, y);
return res;
}
int get_val(int u, int k)
{
while (true)
{
if (tr[tr[u].s[0]].size >= k) u = tr[u].s[0];
else if (tr[tr[u].s[0]].size + 1 == k) return tr[u].v;
else k -= tr[tr[u].s[0]].size + 1, u = tr[u].s[1];
}
return -1;
}
int get_pre(int v)
{
split(root, v - 1, x, y);
int res = get_val(x, tr[x].size);
root = merge(x, y);
return res;
}
int get_next(int v)
{
split(root, v, x, y);
int res = get_val(y, 1);
root = merge(x, y);
return res;
}
int main()
{
cin >> n;
while (n -- )
{
int opt;
cin >> opt >> x;
if (opt == 1) insert(x);
if (opt == 2) remove(x);
if (opt == 3) cout << get_rank(x) << endl;
if (opt == 4) cout << get_val(root, x) << endl;
if (opt == 5) cout << get_pre(x) << endl;
if (opt == 6) cout << get_next(x) << endl;
}
return 0;
}
2. 文艺平衡树
#include <iostream>
#include <cstring>
#include <cstdio>
#include <algorithm>
using namespace std;
const int N = 100010;
int x, y, z;
int n;
int m;
int root, idx;
struct Tree
{
int s[2];
int v;
int size;
int dat;
int rev;
}tr[N];
void pushup(int u)
{
tr[u].size = tr[tr[u].s[0]].size + tr[tr[u].s[1]].size + 1;
}
void pushdown(int u)
{
if (tr[u].rev)
{
swap(tr[u].s[0], tr[u].s[1]);
tr[tr[u].s[0]].rev ^= 1, tr[tr[u].s[1]].rev ^= 1;
tr[u].rev = 0;
}
}
int init(int v)
{
idx ++ ;
tr[idx].size = 1, tr[idx].v = v, tr[idx].dat = rand();
return idx;
}
void split(int u, int v, int &x, int &y)
{
if (!u) x = y = 0;
else
{
pushdown(u);
if (tr[tr[u].s[0]].size + 1 <= v) x = u, split(tr[u].s[1], v - tr[tr[u].s[0]].size - 1, tr[u].s[1], y);
else y = u, split(tr[u].s[0], v, x, tr[u].s[0]);
pushup(u);
}
}
int merge(int a, int b)
{
if (!a || !b) return a + b;
if (tr[a].dat < tr[b].dat)
{
pushdown(a);
tr[a].s[1] = merge(tr[a].s[1], b);
pushup(a);
return a;
}
else
{
pushdown(b);
tr[b].s[0] = merge(a, tr[b].s[0]);
pushup(b);
return b;
}
}
void insert(int v)
{
split(root, v, x, y);
root = merge(merge(x, init(v)), y);
}
void print(int u)
{
pushdown(u);
if (tr[u].s[0]) print(tr[u].s[0]);
printf("%d ", tr[u].v);
if (tr[u].s[1]) print(tr[u].s[1]);
}
int main()
{
cin >> n >> m;
for (int i = 1; i <= n; i ++ ) insert(i);
while (m -- )
{
int l, r;
cin >> l >> r;
split(root, l - 1, x, y);
split(y, r - l + 1, y, z);
tr[y].rev ^= 1;
root = merge(x, merge(y, z));
}
print(root);
return 0;
}

浙公网安备 33010602011771号