fhq Treap模板

普通平衡树(按权值划分)

#include <iostream>
#include <random>//rand()最大32767
using namespace std;
mt19937 dice(random_device{}());
const int N = 1e5 + 7;
//rd[i]-第i个结点的随机数,sz[i]-以i为根的子树中结点的个数
int son[N][2], val[N], rd[N], sz[N], root;
int new_node(int v) {
	static int ct;
	sz[++ct] = 1, val[ct] = v, rd[ct] = dice();
	return ct;
}
void update(int x) {//更新以x为根节点的整棵树的元素个数
	sz[x] = 1 + sz[ son[x][0] ] + sz[ son[x][1] ];
}
//合并以x和y为根的两棵子树,x必须在y左边,可以是父结点或左儿子
int merge(int x, int y) {
	//x==0则返回y,y==0则返回x
	if (!x || !y) return x + y;
	if (rd[x] < rd[y]) {//维护小根堆的性质不变
		son[x][1] = merge(son[x][1], y);
		update(x);
		return x;
	} else {
		son[y][0] = merge(x, son[y][0]);
		update(y);
		return y;
	}
}
//按结点权值分裂,将小于等于v的所有结点分裂为一棵以x为根结点的树
//其余结点分给以y为根结点的树
void split(int rt, int v, int &x, int &y) {
	if (!rt) { x = y = 0; return; }
	if (val[rt] <= v)
		x = rt, split(son[x][1], v, son[x][1], y);
	else
		y = rt, split(son[y][0], v, x, son[y][0]);
	update(rt);
}
void insert(int v) {
	int x, y;
	//将小于等于v的结点split出来,以x作为根,剩余元素以y为根
	split(root, v, x, y);//x和y的参数作为引用参数,在split中被赋值
	//合并时第一个参数的树中的值都小于等于第二个参数的树中的值
	root = merge(merge(x, new_node(v)), y);
}
void rm(int v) {
	//我们把小于v的和大于v的部分都单独分裂出来,把中间等于v的去掉一个
	int x, y, z;
	//将大于v的结点分给z,将小于v的结点分给x,等于v的就是y
	split(root, v, x, z), split(x, v-1, x, y);
	//直接将y的左儿子和右儿子merge,就去掉了y自己
	y = merge(son[y][0], son[y][1]);
	root = merge(merge(x, y), z);
}
void rank_v(int v) {
	int x, y;
	split(root, v-1, x, y);
	printf("%d\n", sz[x] + 1);
	root = merge(x, y);
}
void kth(int rt, int k) {
	while (k-1 != sz[ son[rt][0] ]) {//根结点不是第k个元素
		if (k <= sz[ son[rt][0] ])
			rt = son[rt][0];
		else 
			k -= sz[ son[rt][0] ] + 1, rt = son[rt][1];
	}
	printf("%d\n", val[rt]);
}
void pre(int v) {
	int x, y;
	split(root, v-1, x, y);
	kth(x, sz[x]);
	root = merge(x, y);
}
void post(int v) {
	int x, y;
	split(root, v, x, y);
	kth(y, 1);
	root = merge(x, y);
}
int main() {
	int n;
	scanf("%d", &n);
	while (n--) {
		int op, v;
		scanf("%d%d", &op, &v);
		switch(op) {
			case 1: insert(v);		break;
			case 2: rm(v);			break;
			case 3: rank_v(v);		break;
			case 4:	kth(root, v); 	break;
			case 5: pre(v);			break;
			case 6: post(v);		break;
		}
	}
	return 0;
} 

文艺平衡树(按rank划分)

#include <iostream>
#include <random>
using namespace std;
mt19937 dice(random_device{}());
const int N = 1e5 + 7;
int son[N][2], root, val[N], size[N], rk[N], n;
bool tag[N];
int new_node(int v) {
    static int sz;
    val[++sz] = v, size[sz] = 1, rk[sz] = dice();
    return sz;
}
void update(int u) {
    size[u] = 1 + size[ son[u][0] ] + size[ son[u][1] ];
} 
int build(int lo, int hi) {//递归的build都是按先序进行创建
    if (lo > hi) return 0;
    int mid = (lo+hi)>>1, v = mid-1;
    int cur = new_node(v);
    son[cur][0] = build(lo, mid-1);
    son[cur][1] = build(mid+1, hi);
    update(cur);
    return cur;
}
void pushdown(int x) {//懒标记,一次只下传一层
    if (!x || !tag[x]) return;
    tag[x] = 0;
    std::swap(son[x][0], son[x][1]);
    if (son[x][0]) tag[ son[x][0] ] ^= 1;
    if (son[x][1]) tag[ son[x][1] ] ^= 1;
}
int merge(int x, int y) {
    if (!x || !y) return x + y;
    pushdown(x), pushdown(y);
    if (rk[x] < rk[y]) {
        son[x][1] = merge(son[x][1], y);
        update(x);
        return x;
    }
    son[y][0] = merge(x, son[y][0]);
    update(y);
    return y;
}
void split(int cur, int k, int &x, int &y) {//算上哨兵,应该找k+1
    if (!cur) { x = y = 0; return; }
    pushdown(cur);//下传懒标记
    if (k <= size[ son[cur][0] ])//cur排名在前k个以外
        y = cur, split(son[y][0], k, x, son[y][0]);
    else //cur排名在前k个以内
        x = cur, split(son[x][1], k-1-size[ son[x][0] ], son[x][1], y);
    update(cur);
}
void rot(int lo, int hi) {
    int u, v, s, t;
    split(root, hi+1, u, v);
    split(u, lo, s, t);
    tag[t] ^= 1;
    root = merge(merge(s, t), v);
}
void dfs(int u) {//中序遍历,带懒标记的
    if (!u) return;
    pushdown(u);
    dfs(son[u][0]);
    if (val[u]>=1 && val[u]<=n)
        printf("%d ", val[u]);
    dfs(son[u][1]);
}
int main() {
    int m, l, r;
    scanf("%d%d", &n, &m);
    root = build(1, n+2);
    while (m--) {
        scanf("%d%d", &l, &r);
        rot(l, r);
    }
    dfs(root);
    return 0;
}
posted @ 2024-09-03 09:09  飞花阁  阅读(6)  评论(0)    收藏  举报
//雪花飘落效果