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);
  	}
  }
  1. 按节点键值分裂
  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;
}
posted @ 2022-01-31 18:51  Link-Cut-Y  阅读(86)  评论(0)    收藏  举报