OI模板 平衡树

本文介绍了两种平衡树数据结构:OI模板平衡树和FHQ-Treap,重点讲解了区间操作、区间翻转等高级特性,适合对数据结构和算法感兴趣的开发者。通过实例演示了如何使用这两种结构进行插入、删除、查找等操作,并在解决实际问题中展示了其应用价值。
摘要由CSDN通过智能技术生成

OI模板 平衡树

普通平衡树-FHQ Treap

const int N = 500010;
int ch[N][2], val[N], pri[N], siz[N], tot;
int root, x, y, z;

void update(int x){
	siz[x] = siz[ch[x][0]] + siz[ch[x][1]] + 1;
}
int newnode(int v){
	siz[++tot] = 1;
	val[tot] = v;
	pri[tot] = rand();
	return tot;
}
void init(){
	srand(time(NULL));
	tot = root = x = y = z = 0;
	memset(ch, 0, sizeof(ch));
	memset(val, 0, sizeof(val));
	memset(pri, 0, sizeof(pri));
	memset(siz, 0, sizeof(siz));
	newnode(0xcfcfcfcf);
	newnode(0x3f3f3f3f);
}
int merge(int x, int y){
	if(!x || !y){
		return x + y;
	}
	if(pri[x] < pri[y]){
		ch[x][1] = merge(ch[x][1], y);
		update(x);
		return x;
	} else {
		ch[y][0] = merge(x, ch[y][0]);
		update(y);
		return y;
	}
}
void split(int p, int k, int &x, int &y){
	if(!p){
		x = y = 0;
		return;
	}
	if(val[p] <= k){
		x = p;
		split(ch[p][1], k, ch[p][1], y);
	} else {
		y = p;
		split(ch[p][0], k, x, ch[p][0]);
	}
	update(p);
}
int kth(int p, int k){
	while(true){
		if(k <= siz[ch[p][0]]){
			p = ch[p][0];
		} else if(k == siz[ch[p][0]] + 1){
			return p;
		} else {
			k -= siz[ch[p][0]] + 1;
			p = ch[p][1];
		}
	}
}
void ins(int k){
	split(root, k, x, y);
	root = merge(merge(x, newnode(k)), y);
}
void del(int k){
	split(root, k, x, z);
	split(x, k-1, x, y);
	y = merge(ch[y][0], ch[y][1]);
	root = merge(merge(x, y), z);
}
int getrank(int k){
	split(root, k-1, x, y);
	int ans = siz[x] + 1;
	root = merge(x, y);
	return ans;
}
int getval(int k){
	return val[kth(root, k)];
}
int getpre(int k){
	split(root, k-1, x, y);
	int ans = val[kth(x, siz[x])];
	root = merge(x, y);
	return ans;
}
int getnxt(int k){
	split(root, k, x, y);
	int ans = val[kth(y, 1)];
	root = merge(x, y);
	return ans;
}

void solve(){
	init();
	int n = rdi;
	while(n--){
		int op = rdi;
		int k = rdi;
		if(op == 1){
			ins(k);
		} else if(op == 2){
			del(k);
		} else if(op == 3){
			writen(getrank(k));
		} else if(op == 4){
			writen(getval(k));
		} else if(op == 5){
			writen(getpre(k));
		} else {
			writen(getnxt(k));
		}
	}
}

FHQ-Treap:区间操作-区间翻转(文艺平衡树)

const int N = 500010;
int ch[N][2], val[N], pri[N], siz[N], rev[N], tot;
int root, x, y, z, n, m;

void update(int x){
	siz[x] = siz[ch[x][0]] + siz[ch[x][1]] + 1;
}
int newnode(int v){
	siz[++tot] = 1;
	val[tot] = v;
	pri[tot] = rand();
	return tot;
}
void spread(int x){
	swap(ch[x][0], ch[x][1]);
	if(ch[x][0]){
		rev[ch[x][0]] ^= 1;
	}
	if(ch[x][1]){
		rev[ch[x][1]] ^= 1;
	}
	rev[x] = 0;
}
int merge(int x, int y){
	if(!x || !y){
		return x + y;
	}
	if(pri[x] < pri[y]){
		if(rev[x]){
			spread(x);
		}
		ch[x][1] = merge(ch[x][1], y);
		update(x);
		return x;
	} else {
		if(rev[y]){
			spread(y);
		}
		ch[y][0] = merge(x, ch[y][0]);
		update(y);
		return y;
	}
}
void split(int p, int k, int &x, int &y){
	if(!p){
		x = y = 0;
		return;
	}
	if(rev[p]){
		spread(p);
	}
	if(siz[ch[p][0]] + 1 <= k){
		x = p;
		split(ch[p][1], k-siz[ch[p][0]]-1, ch[p][1], y);
	} else {
		y = p;
		split(ch[p][0], k, x, ch[p][0]);
	}
	update(p);
}
void init(){
	srand(time(NULL));
	tot = root = x = y = z = 0;
	memset(ch, 0, sizeof(ch));
	memset(val, 0, sizeof(val));
	memset(pri, 0, sizeof(pri));
	memset(siz, 0, sizeof(siz));
	memset(rev, 0, sizeof(rev));
	newnode(0xcfcfcfcf);
	newnode(0x3f3f3f3f);
	for(int i = 1; i <= n; ++ i){
		root = merge(root, newnode(i));
	}
}
void reverse(int l, int r){
	split(root, l-1, x, y);
	split(y, r-l+1, y, z);
	rev[y] ^= 1;
	root = merge(x, merge(y, z));
}
void print(int p){
	if(!p){
		return;
	}
	if(rev[p]){
		spread(p);
	}
	print(ch[p][0]);
	write(val[p]);
	print(ch[p][1]);
}

void solve(){
	n = rdi;
	m = rdi;
	init();
	while(m--){
		int l = rdi;
		int r = rdi;
		reverse(l, r);
	}
	print(root);
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值