替罪羊树 TLE 63分求调
  • 板块学术版
  • 楼主YU_QE
  • 当前回复1
  • 已保存回复1
  • 发布时间2025/7/24 20:52
  • 上次更新2025/7/25 10:25:45
查看原帖
替罪羊树 TLE 63分求调
1266309
YU_QE楼主2025/7/24 20:52

RT,调了很久,但不知道为什么 TLE了

#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 为数量
int can_use_Nodes[N], top; // 可用节点
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[++top] = 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--]; 
		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) 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 = 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() {
	for (int i = N - 1; i >= 1; --i) can_use_Nodes[++top] = i;
	int q; 
	scanf("%d", &q);
	while(q--) {
		int opt, x; cin >> opt >> x;
		switch(opt) {
			case 1 : Insert(root, x); break;
			case 2 : Del(x); break;
			case 3 : printf("%d\n", Rank(root, x) + 1); break;
			case 4 : printf("%d\n", kth(x)); break;
			case 5 : printf("%d\n", kth(Rank(root, x))); break;
			case 6 : printf("%d\n", kth(Rank(root, x + 1) + 1)); break;
		}
	}
}
2025/7/24 20:52
加载中...