替罪羊树

替罪羊树

暴力重构的思想,如果树不够平衡,那么就拍扁重构即可

和 treap 的操作大致都一样就是了,但常数挺小的,可以卡常使用

const int N = 2005000;
struct node {
	int ls, rs, siz, sum;
	int key, val;
	#define key(k) p[k].key
	#define val(k) p[k].val
	#define ls(k) p[k].ls
	#define rs(k) p[k].rs
	#define siz(k) p[k].siz
	#define sum(k) p[k].sum
}p[N];
int rt, cnt;
const double A = 0.8;
bool judge(int k) {
	return val(k) && A * siz(k) < max(siz(ls(k)), siz(rs(k)));
}

void update(int k) {
	siz(k) = siz(ls(k)) + siz(rs(k)) + (val(k) ? 1 : 0);
	sum(k) = sum(ls(k)) + sum(rs(k)) + val(k);
}

int st[N], tp;
void pia(int k) {
	if (ls(k)) pia(ls(k));
	if (val(k)) st[++tp] = k;
	if (rs(k)) pia(rs(k));
	return;
}

int rebuild(int l, int r) {
	if (l > r) return 0;
	int mid = (l + r) >> 1;
	ls(st[mid]) = rebuild(l, mid - 1);
	rs(st[mid]) = rebuild(mid + 1, r);
	return update(st[mid]), st[mid];
}
int maintain(int p) {
	return tp = 0, pia(p), rebuild(1, tp);
}
void insert(int &x, int val) {
	if (!x) {
		x = ++cnt, key(x) = val;
		val(x) = siz(x) = sum(x) = 1;
	}
	else {
		if (key(x) == val) val(x)++;
		else if (val < key(x)) insert(ls(x), val);
		else insert(rs(x), val);
		update(x); judge(x) && (x = maintain(x));
	}
}
void del(int &x, int val) {
	sum(x)--;
	if (key(x) == val) val(x)--;
	else key(x) > val ? del(ls(x), val) : del(rs(x), val);
	update(x), judge(x) && (x = maintain(x));
}
int rkup(int x, int k) {
	int nw = 0;
	while (1) {
		if (!x) return nw;
		if (key(x) == k) return nw + sum(ls(x)) + val(x);
		if (key(x) <= k) nw += sum(ls(x)) + val(x), x = rs(x);
		else x = ls(x);
	}
}
int rkdw(int x, int k) {
	int nw = 1;
	while (1) {
		if (!x) return nw;
		if (key(x) == k) return nw + sum(ls(x));
		if (key(x) <= k) nw += sum(ls(x)) + val(x), x = rs(x);
		else x = ls(x);
	}
}

int get(int k) {
	int x = rt;
	while (1) {
		if (sum(ls(x)) >= k) x = ls(x);
		else if (sum(ls(x)) + val(x) >= k) return key(x);
		else k -= sum(ls(x)) + val(x), x = rs(x);
	}
	return 1;
}

int n, t, x, m, las, ans;
int main() {
	for (read(n), read(m); n; n--) 
		read(x), insert(rt, x);
	for (; m; m--) {
		read(t), read(x), x ^= las;
		if (t == 1) insert(rt, x);
		else if (t == 2) del(rt, x);
		else if (t == 3) las = rkdw(rt, x);
		else if (t == 4) las = get(x);
		else if (t == 5) las = get(rkdw(rt, x) - 1);
		else las = get(rkup(rt, x) + 1);
		if (t >= 3) ans ^= las;
	}
	write(ans);
	return 0;
}
原文地址:https://www.cnblogs.com/Hs-black/p/13362704.html