[洛谷P3369]【模板】普通平衡树

题目大意:需要提供以下操作:

  1. 插入 $x$ 数
  2. 删除 $x$ 数(若有多个相同的数,因只删除一个)
  3. 查询 $x$ 数的排名(排名定义为比当前数小的数的个数 $+1$ 。若有多个相同的数,因输出最小的排名)
  4. 查询排名为 $x$ 的数
  5. 求 $x$ 的前驱(前驱定义为小于 $x$ ,且最大的数)
  6. 求 $x$ 的后继(后继定义为大于 $x$ ,且最小的数)

题解:平衡树,treap

卡点:

C++ Code:

#include <cstdio>
#include <cstdlib>
#define maxn 100050
using namespace std;
int n, op, x;
struct treap {
	int lc[maxn], rc[maxn], val[maxn], num[maxn], sz[maxn];
	int root, idx;
	int ta, tb, tmp, res;
	int update(int p) {
		sz[p] = sz[lc[p]] + sz[rc[p]] + 1;
		return p;
	}
	int nw(int p) {
		val[++idx] = p;
		sz[idx] = 1;
		num[idx] = rand();
		return idx;
	}
	void split(int rt, int k, int &x, int &y) {
		if (!rt) x = y = 0;
		else {
			if (val[rt] <= k) split(rc[rt], k, rc[rt], y), x = update(rt);
			else split(lc[rt], k, x, lc[rt]), y = update(rt);
		}
	}
	int merge(int x, int y) {
		if (!x || !y) return x|y;
		if (num[x] > num[y]) {rc[x] = merge(rc[x], y); return update(x);}
		else {lc[y] = merge(x, lc[y]); return update(y);}
	}
	void insert(int p) {
		split(root, p, ta, tb);
		root = merge(merge(ta, nw(p)), tb);
	}
	void erase(int p) {
		split(root, p, ta, tb);
		split(ta, p - 1, ta, tmp);
		root = merge(ta, merge(merge(lc[tmp], rc[tmp]), tb));
	}
	int gtrnk(int p) {
		split(root, p - 1, ta, tb);
		res = sz[ta] + 1;
		root = merge(ta, tb);
		return res;
	}
	int gtk_th(int p, int k) {
		while (true) {
			if (sz[lc[p]] >= k) p = lc[p];
			else
				if (sz[lc[p]] + 1 == k) return val[p];
				else k -= sz[lc[p]] + 1, p = rc[p];
		}
	}
	int pre(int p) {
		split(root, p - 1, ta, tb);
		res = gtk_th(ta, sz[ta]);
		root = merge(ta, tb);
		return res;
	}
	int nxt(int p) {
		split(root, p, ta, tb);
		res = gtk_th(tb, 1);
		root = merge(ta, tb);
		return res;
	}
} T;

int main() {
	srand(20040826);
	scanf("%d", &n);
	while (n--) {
		scanf("%d%d", &op, &x);
		switch (op) {
			case 1: {
				T.insert(x);
				break;
			}
			case 2: {
				T.erase(x);
				break;
			}
			case 3: {
				printf("%d\n", T.gtrnk(x));
				break;
			}
			case 4: {
				printf("%d\n", T.gtk_th(T.root, x));
				break;
			}
			case 5: {
				printf("%d\n", T.pre(x));
				break;
			}
			case 6: {
				printf("%d\n", T.nxt(x));
				break;
			}
		}
	}
	return 0;
}

  

猜你喜欢

转载自www.cnblogs.com/Memory-of-winter/p/9335214.html