替罪羊树

#include <bits/stdc++.h>
using namespace std;
const int MAXN = 1e5 + 5;
const double alpha = 0.7;

struct Node
{
	int l, r, val, size, cnt;
	bool deleted;
} tr[MAXN];
int idx, root;

bool isbad(int u)
{
	return tr[tr[u].l].cnt > alpha * tr[u].cnt + 5 || // 左子树失衡检测
		   tr[tr[u].r].cnt > alpha * tr[u].cnt + 5;	  // 右子树失衡检测
}

void maintain(int u)
{
	tr[u].size = !tr[u].deleted + tr[tr[u].l].size + tr[tr[u].r].size; // 更新有效节点数(排除已删除)
	tr[u].cnt = 1 + tr[tr[u].l].cnt + tr[tr[u].r].cnt;				   // 更新总节点数(包含删除节点)
}

void dfs(int u, vector<int> &v)
{
	if (!u)
		return;		 // 空节点直接返回
	dfs(tr[u].l, v); // 递归遍历左子树
	if (!tr[u].deleted)
		v.push_back(u); // 收集未删除的有效节点
	dfs(tr[u].r, v);	// 递归遍历右子树
}

int build(vector<int> &v, int l, int r)
{
	if (l >= r)
		return 0; // 基准条件:空区间返回空指针

	int mid = (l + r) >> 1; // 取中间元素作为当前根节点
	int u = v[mid];			// 获取预存节点索引

	tr[u].l = build(v, l, mid);		// 递归构建左子树(处理左半区间 [l, mid))
	tr[u].r = build(v, mid + 1, r); // 递归构建右子树(处理右半区间 [mid+1, r))

	maintain(u); // 维护节点统计信息(size/cnt)
	return u;	 // 返回当前构建的子树根节点
}

void rebuild(int &u)
{
	vector<int> v;			   // 存储有效节点索引
	dfs(u, v);				   // 中序遍历收集未删除节点
	u = build(v, 0, v.size()); // 重构平衡树并更新根节点
}

void insert(int x, int &u)
{
	if (!u) // 当前为空节点,创建新节点
	{
		u = ++idx;
		tr[u] = {0, 0, x, 1, 1, false}; // 初始化节点属性
		return;
	}
	tr[u].size++; // 更新有效节点数
	tr[u].cnt++;  // 更新总节点数(含删除节点)

	// 递归插入子树
	if (x >= tr[u].val)
		insert(x, tr[u].r); // 插入右子树
	else
		insert(x, tr[u].l); // 插入左子树

	if (isbad(u))	// 检查平衡性
		rebuild(u); // 触发重构
}

int get_rank(int u, int x)
{
	int ans = 1; // 初始化排名(从1开始计数)
	while (u)
	{
		if (tr[u].val >= x)
			u = tr[u].l; // 目标在左子树(性质)
		else
		{
			// 累加左子树有效节点数 + 当前节点是否有效
			ans += tr[tr[u].l].size + !tr[u].deleted;
			u = tr[u].r; // 继续搜索右子树
		}
	}
	return ans; // 返回最终排名
}

int kth(int u, int x)
{
	while (u)
	{
		// 命中条件:当前节点有效,且左子树有效节点数+1等于目标排名
		if (!tr[u].deleted && tr[tr[u].l].size + 1 == x)
			return tr[u].val;

		// 左子树足够大时搜索左子树
		if (tr[tr[u].l].size >= x)
			u = tr[u].l;
		else
		{
			// 调整目标排名:扣除左子树和当前节点有效值
			x -= tr[tr[u].l].size + !tr[u].deleted;
			u = tr[u].r; // 转向右子树搜索剩余排名
		}
	}
	return -1; // 未找到有效结果
}

void erase(int u, int rk)
{
	// 找到目标节点时进行惰性删除
	if (!tr[u].deleted && rk == tr[tr[u].l].size + 1)
	{
		tr[u].deleted = 1; // 标记为已删除
		tr[u].size--;	   // 更新有效节点数
		return;
	}
	// 路径更新:当前子树有效节点数减1
	tr[u].size--;
	// 递归查找删除位置
	if (rk <= tr[tr[u].l].size + !tr[u].deleted)
		erase(tr[u].l, rk); // 目标在左子树
	else
		// 调整目标排名后搜索右子树
		erase(tr[u].r, rk - tr[tr[u].l].size - !tr[u].deleted);
}

posted @ 2025-02-25 21:25  流氓兔LMT  阅读(12)  评论(0)    收藏  举报