替罪羊树63分求条
查看原帖
替罪羊树63分求条
1266309
YU_QE楼主2025/7/22 15:31
#include <bits/stdc++.h>

constexpr int N = 1e6 + 10;
constexpr double alpha = 0.75; // 不平衡率,一般用 alpha 表示

using namespace std;

struct Node {
	int left_son, right_son; // 左右儿子
	int val; // 节点存的数字
	int all_size; // 当前子树的节点数量,包括已被删除的节点
	int size; // 子树上实际的存储数字的数量
	int del; // del = 1 表示这个节点存有数字,反之被删除
}tree[N];

int order[N], cnt; // 记录被拍平后的结果,即那些存有数字的节点,cnt 为数量
stack<int> can_use_Nodes; // 可用节点
int root = 0; // 根节点,注意重建时根节点会发生变化

void in_order (int u) { // 中序遍历,“拍平”摧毁这棵子树
	if (!u) return; // 已经到达叶子节点,退出 
	in_order(tree[u].left_son); // 先遍历左子树 
	if (tree[u].del) order[++cnt] = u; // 如果该节点有数字,读取它 
	else can_use_Nodes.push(u); // 回收该节点,等待重新分配使用 
	in_order(tree[u].right_son); // 再遍历右子树 
}

void Initnode (int u) { // 重置节点参数 
	tree[u].left_son = tree[u].right_son = 0;
	tree[u].size = tree[u].all_size = tree[u].del = 1;
}

void Update (int u) { 
	tree[u].size = tree[tree[u].left_son].size + tree[tree[u].right_son].size + 1;
	tree[u].all_size = tree[tree[u].left_son].all_size + tree[tree[u].right_son].all_size + 1;
}

void build (int l, int r, int &u) { // 把拍平的子树拎起来,重建
	int mid = (l + r) >> 1;
	u = order[mid]; // 将新的根设为中点,使重构出的树尽量平衡 
	if (l == r) {
		Initnode(u);
		return;
	} // 如果是叶子节点,返回 
	if (l < mid) build(l, mid - 1, tree[u].left_son); // 如果有左子树,重建左子树 
	if (l == mid) tree[u].left_son = 0; // 没有就把左儿子标记没有 
	build(mid + 1, r, tree[u].right_son);
	Update(u);
}

void rebuild(int &u) {
	cnt = 0;
	in_order(u);
	if (cnt) build(1, cnt, u);
	else u = 0;
}

bool not_balance(int u) {
	double x = tree[u].size * alpha;
	double y = max(tree[tree[u].left_son].size, tree[tree[u].right_son].size);
	if (x <= y) return false;
	return true;
}

void Insert(int &u, int x) {
	if (!u) {
		u = can_use_Nodes.top();
		can_use_Nodes.pop();
		tree[u].val = x;
		Initnode(u);
		return;
	}
	tree[u].size += 1;
	tree[u].all_size += 1;
	
	if (tree[u].val >= x) Insert(tree[u].left_son, x);
	else Insert(tree[u].right_son, x);
	if (not_balance(u)) rebuild(u);
}

int Rank(int u, int x) {
	if (u == 0) return 0;
	if (x > tree[u].val) return tree[tree[u].left_son].size + tree[u].del + Rank(tree[u].right_son, x);
	return Rank(tree[u].left_son, x);
}

int kth(int k) {
	int u = root;
	while(u) {
		if (tree[u].del && tree[tree[u].left_son].size + 1 == k) return tree[u].val;
		else if (tree[tree[u].left_son].size >= k) u = tree[u].left_son;
		else {
			k -= tree[tree[u].left_son].size + tree[u].del;
			u = tree[u].right_son;
		}
	}
	return tree[u].val;
}

void Del_k (int &u, int k) {
	tree[u].size -= 1;
	if (tree[u].del && tree[tree[u].left_son].size + 1 == k) {
		tree[u].del = 0;
		return;
	}
	if (tree[tree[u].left_son].size + tree[u].del >= k) Del_k(tree[u].left_son, k);
	else Del_k(tree[u].right_son, k - tree[tree[u].left_son].size - tree[u].del);
}

void Del(int x) {
	Del_k(root, Rank(root, x) + 1);
	if (tree[root].all_size * alpha >= tree[root].size) rebuild(root);
}

int main() {
	ios::sync_with_stdio(false), cin.tie(0), cout.tie(0);
	for (int i = N - 1; i >= 1; --i) can_use_Nodes.push(i);
	int q; cin >> q;
	while(q--) {
		int opt, x; cin >> opt >> x;
		switch(opt) {
			case 1 : Insert(root, x); break;
			case 2 : Del(x); break;
			case 3 : cout << Rank(root, x) + 1 << '\n'; break;
			case 4 : cout << kth(x) << '\n'; break;
			case 5 : cout << kth(Rank(root, x)) << '\n'; break;
		    case 6 : cout << kth(Rank(root, x + 1) + 1) << '\n'; break;
		}
	}
}
2025/7/22 15:31
加载中...