[Luogu P6136] Ordinary balanced tree (data enhanced version)

Ordinary Balance Tree (Data Enhanced Version)

Title link: luogu P6136

General idea

The enhanced version of the balanced tree template question requires maintenance of some operations. Insert a number, delete a number, query the ranking of a number, query the number that has been ranked, and find the predecessor and successor.
Mandatory online, wider range.

Ideas

This question is actually luogu P3369 , in fact, the code is similar to it.
( The blog I wrote about the topic uses the scapegoat tree approach, and this topic also uses the scapegoat tree )

Obviously, this can be done by using a balanced tree, but some things need to be changed.

First, decode the read.
Next, for the number that is asked about the ranking, if the ranking is not where the ranking is, the last one must be selected, because the largest number with a ranking less than it is the last ranked.

Then it's fine.
If you don’t know how to write a scapegoat, you can read my regular blog .

Code

//替罪羊

#include<cstdio>
#define alpha 0.7

using namespace std;

struct Tree {
    
    
	int l, r, val, fa, num, sum;
}tree[2000001];
struct reTree {
    
    
	int val, num;
}retree[2000001];
int n, m, op, x, root, sta[2000001];
int maxn, tot, tott;
int last_answer, final_answer;

bool check(int x) {
    
    
	if (!tree[x].num) return 0;
	if (tree[tree[x].l].sum >= (double)(alpha * tree[x].sum)) return 1;
	if (tree[tree[x].r].sum >= (double)(alpha * tree[x].sum)) return 1;
	return 0;
}

void up(int now) {
    
    
	tree[now].sum = tree[now].num;
	if (tree[now].l) tree[now].sum += tree[tree[now].l].sum;
	if (tree[now].r) tree[now].sum += tree[tree[now].r].sum;
}

void dfs(int x) {
    
    
	sta[++sta[0]] = x;
	if (tree[x].l) dfs(tree[x].l);
	if (tree[x].num) {
    
    
		retree[++tott].val = tree[x].val;
		retree[tott].num = tree[x].num;
	}
	tree[x].sum = 0;
	if (tree[x].r) dfs(tree[x].r);
}

int get_new() {
    
    
	if (sta[0]) {
    
    
		sta[0]--;
		return sta[sta[0] + 1];
	}
	else return ++tot;
}

void make_new(int l, int r, int now, int father) {
    
    
	int mid = (l + r) >> 1;
	tree[now].fa = father;
	tree[now].num = retree[mid].num;
	tree[now].val = retree[mid].val;
	tree[now].sum = 1;
	if (l <= mid - 1) {
    
    
		tree[now].l = get_new();
		make_new(l, mid - 1, tree[now].l, now);
	}
	else tree[now].l = 0;
	if (r >= mid + 1) {
    
    
		tree[now].r = get_new();
		make_new(mid + 1, r, tree[now].r, now);
	}
	else tree[now].r = 0;
	up(now);
}

void rebuild(int x) {
    
    
	if (!x) return ;
	tott = 0;
	dfs(x);
	int now = get_new();
	if (x == root) root = now;
	tree[now].fa = tree[x].fa;
	int mid = (1 + tott) >> 1;
	if (retree[mid].val < tree[tree[now].fa].val) tree[tree[now].fa].l = now;
		else tree[tree[now].fa].r = now;
	make_new(1, tott, now, tree[now].fa);
}

void insert(int x, bool need_build) {
    
    
	if (root == 0) {
    
    
		root = 1;
		tot = 1;
		tree[1] = (Tree){
    
    0, 0, x, 0, tree[1].num + 1, tree[1].sum + 1};
		return ;
	}
	
	int now = root;
	while (tree[now].sum) {
    
    
		if (x == tree[now].val) {
    
    
			tree[now].num++;
			tree[now].sum++;
			return ;
		}
		if (!tree[now].l && x < tree[now].val) break;
		if (!tree[now].r && x > tree[now].val) break;
		tree[now].sum++;
		if (x < tree[now].val) now = tree[now].l;
			else if (x > tree[now].val) now = tree[now].r;
	}
	if (x == tree[now].val) {
    
    
		tree[now].num++;
		tree[now].sum++;
		return ;
	}
	
	tree[now].sum++;
	
	int tmp = now;
	if (x < tree[now].val) now = tree[now].l = ++tot;
		else if (x > tree[now].val) now = tree[now].r = ++tot;
	tree[now].num++;
	tree[now].sum++;
	tree[now].val = x;
	if (tmp != now) tree[now].fa = tmp;
	
	int first_fix = 0;
	while (now != root) {
    
    
		now = tree[now].fa;
		if (check(now)) first_fix = now;
	}
	if (need_build && first_fix) rebuild(first_fix);
}

int tree_place(int x) {
    
    
	int now = root;
	while (tree[now].val != x && tree[now].sum != 0) {
    
    
		if (x <= tree[now].val) now = tree[now].l;
			else now = tree[now].r;
	}
	return now;
}

void delete_(int x, int need_build) {
    
    
	tree[x].num--;
	tree[x].sum--;
	int first_fix = 0;
	while (x != root) {
    
    
		x = tree[x].fa;
		tree[x].sum--;
		if (check(x)) first_fix = x;
	}
	
	if (need_build && first_fix) rebuild(first_fix);
}

int get_rank(int x) {
    
    
	insert(x, 0);
	
	int now = tree_place(x);
	
	int re = tree[tree[now].l].sum + 1;
	while (now != root) {
    
    
		if (tree[tree[now].fa].r == now)
			re += tree[tree[tree[now].fa].l].sum + tree[tree[now].fa].num;
		now = tree[now].fa;
	}
	
	delete_(tree_place(x), 0);
	
	return re;
}

int get_num(int x) {
    
    
	int now = root;
	while (x) {
    
    
		if (x <= tree[tree[now].l].sum) now = tree[now].l;
			else if (x <= tree[tree[now].l].sum + tree[now].num) return tree[now].val;
				else {
    
    
					x -= tree[tree[now].l].sum + tree[now].num;
					now = tree[now].r;
				}
	}
	return tree[now].fa;
}

int pre(int x) {
    
    
	insert(x, 0);
	int need_rank = get_rank(x) - 1;
	delete_(tree_place(x), 0);
	return get_num(need_rank);
}

int suc(int x) {
    
    
	insert(x + 1, 0);
	int need_rank = get_rank(x + 1);
	delete_(tree_place(x + 1), 0);
	return get_num(need_rank);
}

int read() {
    
    
	int re = 0;
	char c = getchar();
	while (c < '0' || c > '9') c = getchar();
	while (c >= '0' && c <= '9') {
    
    
		re = re * 10 + c - '0';
		c = getchar();
	}
	return re;
}

void write(int x) {
    
    
	if (x > 9) write(x / 10);
	putchar(x % 10 + '0');
}

int main() {
    
    
	n = read();
	m = read();
	
	for (int i = 1; i <= n; i++) {
    
    
		x = read();
		insert(x, 1);
	}
	
	for (int i = 1; i <= m; i++) {
    
    
		op = read();
		x = read();
		
		x ^= last_answer;//对答案进行解码

		if (op == 1) {
    
    
			insert(x, 1);
			continue;
		}
		if (op == 2) {
    
    
			delete_(tree_place(x), 1);
			continue;
		}
		if (op == 3) {
    
    
			last_answer = get_rank(x);
			final_answer ^= last_answer;
			continue;
		}
		if (op == 4) {
    
    
			if (x > tree[root].sum) x = tree[root].sum;//不存在,也就是排名排不到那里,那要求的就是排名最后的
			last_answer = get_num(x);
			final_answer ^= last_answer;
			continue;
		}
		if (op == 5) {
    
    
			last_answer = pre(x);
			final_answer ^= last_answer;
			continue;
		}
		if (op == 6) {
    
    
			last_answer = suc(x);
			final_answer ^= last_answer;
			continue;
		}
	}
	
	write(final_answer);
	
	return 0;
}

Guess you like

Origin blog.csdn.net/weixin_43346722/article/details/113885282