社区讨论

帮我看看这个复杂度为啥不对

P6136【模板】普通平衡树(数据加强版)参与者 2已保存回复 1

讨论操作

快速查看讨论及其快照的属性,并进行相关操作。

当前回复
1 条
当前快照
1 份
快照标识符
@mdhaxcv9
此快照首次捕获于
2025/07/24 19:20
7 个月前
此快照最后确认于
2025/11/04 03:48
4 个月前
查看原帖
CPP
#include <bits/stdc++.h>

using namespace std;
mt19937_64 mrand(time(0));

template<int N>
struct FHQ_Treap {
	struct Node {
		int val, sz;
		int l, r;
	} node[N + 1];
	int cnt, rt;

	void init() {
		cnt = rt = 0;
	}

	int new_node(int val) {
		node[++cnt] = {val, 1, 0, 0};
		return cnt;
	}

	void update(int id) {
		node[id].sz = 1;
		if (node[id].l)
			node[id].sz += node[node[id].l].sz;
		if (node[id].r)
			node[id].sz += node[node[id].r].sz;
	}

	void split(int rt, int key, int &l, int &r) {
		if (!rt) {
			l = r = 0;
			return;
		} else {
			if (node[rt].val <= key) {
				l = rt;
				split(node[rt].r, key, node[rt].r, r);
			} else {
				r = rt;
				split(node[rt].l, key, l, node[rt].l);
			}
			update(rt);
		}
	}

	int merge(int l, int r) {
		if (!l)
			return r;
		else if (!r)
			return l;
		else if (mrand() & 1) {
			node[l].r = merge(node[l].r, r);
			update(l);
			return l;
		} else {
			node[r].l = merge(l, node[r].l);
			update(r);
			return r;
		}
	}

	void insert(int x) {
		int now = new_node(x);
		int l = 0, r = 0;
		split(rt, x, l, r);
		rt = merge(merge(l, now), r);
	}

	void erase(int x) {
		int l = 0, r = 0, mid = 0;
		split(rt, x, l, r);
		split(l, x - 1, l, mid);
		mid = merge(node[mid].l, node[mid].r);
		rt = merge(merge(l, mid), r);
	}

	int rank(int x) {
		int l = 0, r = 0;
		split(rt, x - 1, l, r);
		int ret = node[l].sz;
		rt = merge(l, r);
		return ret + 1;
	}

	int kth(int k) {
		int now = rt;
		while (true) {
			if (node[node[now].l].sz >= k)
				now = node[now].l;
			else if (node[node[now].l].sz == k - 1)
				return node[now].val;
			else {
				k -= node[node[now].l].sz + 1;
				now = node[now].r;
			}
		}
		return 0;
	}

	int pre(int x) {
		int l = 0, r = 0;
		split(rt, x - 1, l, r);
		int tmp = l;
		while (node[tmp].r)
			tmp = node[tmp].r;
		rt = merge(l, r);
		return node[tmp].val;
	}

	int nxt(int x) {
		int l = 0, r = 0;
		split(rt, x, l, r);
		int tmp = r;
		while (node[tmp].l)
			tmp = node[tmp].l;
		rt = merge(l, r);
		return node[tmp].val;
	}
};

FHQ_Treap<1100000> treap;

int n, m;

int main() {
	scanf("%d%d", &n, &m);
	treap.init();
	for (int i = 1; i <= n; i++) {
		int tmp;
		cin >> tmp;
		treap.insert(tmp);
	}
	int lst = 0, ans = 0;
	for (int i = 1; i <= m; i++) {
		int opt, x;
		scanf("%d%d", &opt, &x);
		x ^= lst;
		if (opt == 1)
			treap.insert(x);
		else if (opt == 2)
			treap.erase(x);
		else if (opt == 3)
			ans ^= (lst = treap.rank(x));
		else if (opt == 4)
			ans ^= (lst = treap.kth(x));
		else if (opt == 5)
			ans ^= (lst = treap.pre(x));
		else
			ans ^= (lst = treap.nxt(x));
	}
	printf("%d\n", ans);
	return 0;
}
该代码 TLE,6060pts。
和正常 Treap 的区别是,没有使用优先级,而是每次用到优先级的时候随机一个 true/false。

回复

1 条回复,欢迎继续交流。

正在加载回复...