【基本平衡树】TYVJ1728

TYVJ1728

裸的平衡树,直接做,练习代码能力。

注意查询rank时等价于查有多少个比它小的;

虽然建树是小于当前节点key值的放在左子树,但是因为maintain可能使得左子树任意key值不满足严格小于当前节点的key值,所以查询时(如查询第k大,前继,后继)仍需key值小于等于当前节点的key值时就搜索左子树。

具体看代码。


寻找x的前继时,若是x大于当前节点key值,则当前节点也可能是x的前继,所以如果在右子树递归找不到更优的前继时,当前节点则为x前继的前继。(else中的if判断)

inline int Pred(int t,int v)
{
	if (!t) return INF;
	if (v <= key[t]) return Pred(left[t],v);
	else 
	{
		int temp = Pred(right[t],v);
		if (temp == INF) return key[t];
		else return temp;
	}
}
后继类似



CODE:


#include<cstdio>
#include<cstring>
#include<algorithm>
#define INF 1000000000

using namespace std;

const int maxn = 2000005;
int N,T,tot;
int left[maxn],right[maxn],size[maxn],key[maxn];

inline void L_rotate(int &t)
{
	int k = right[t];
	right[t] = left[k];
	left[k] = t;
	size[k] = size[t];
	size[t] = size[left[t]] + size[right[t]] + 1;
	t = k;
}

inline void R_rotate(int &t)
{
	int k = left[t];
	left[t] = right[k];
	right[k] = t;
	size[k] = size[t];
	size[t] = size[left[t]] + size[right[t]] + 1;
	t = k;
}

inline void maintain(int &t,bool flag)
{
	if (!flag)
	{
		if (size[left[left[t]]] > size[right[t]])
			R_rotate(t);
		else if (size[right[left[t]]] > size[right[t]])
			L_rotate(left[t]), R_rotate(t);
		else return;
	} else 
	{
		if (size[right[right[t]]] > size[left[t]])
			L_rotate(t);
		else if (size[left[right[t]]] > size[left[t]])
			R_rotate(right[t]), L_rotate(t);
		else return;
	}
	maintain(left[t],0);
	maintain(right[t],1);
	maintain(t,0);
	maintain(t,1);
}

inline void Insert(int &t,int v)
{
	if (!t)
	{
		t = ++ tot;
		size[t] = 1;
		left[t] = right[t] = 0;
		key[t] = v;
	} else 
	{
		size[t] ++;
		if (v < key[t]) Insert(left[t],v);
		else Insert(right[t],v);
		maintain(t,v >= key[t]);
	}
}

inline int Delete(int &t,int v)
{
	size[t] --;
	if ((key[t] == v) || (v < key[t] && !left[t]) || (v >= key[t] && !right[t]))
	{
		int ret = key[t];
		if (!left[t] || !right[t]) t = left[t] + right[t];
		else key[t] = Delete(left[t],key[t]+1);
		return ret;
	}
	if (v < key[t]) return Delete(left[t],v);
	else return Delete(right[t],v);
}

inline int Rank(int t,int v)
{
	if (!t) return 0;
	if (v <= key[t]) return Rank(left[t],v);
	else return size[left[t]] + 1 + Rank(right[t],v);
}

inline int Select(int t,int v)
{
	int temp = size[left[t]] + 1;
	if (temp == v) return key[t];
	if (v <= temp) return Select(left[t],v);
	else return Select(right[t],v-temp);
}

inline int Pred(int t,int v)
{
	if (!t) return INF;
	if (v <= key[t]) return Pred(left[t],v);
	else 
	{
		int temp = Pred(right[t],v);
		if (temp == INF) return key[t];
		else return temp;
	}
}

inline int Succ(int t,int v)
{
	if (!t) return INF;
	if (v >= key[t]) return Succ(right[t],v);
	else 
	{
		int temp = Succ(left[t],v);
		if (temp == INF) return key[t];
		else return temp;
	}
}

int main()
{
	freopen("tree.in","r",stdin);
	freopen("tree.out","w",stdout);
	scanf("%d",&N);
	while (N--)
	{
		int op,x;
		scanf("%d%d",&op,&x);
		if (op == 1) Insert(T,x);
		if (op == 2) Delete(T,x);
		if (op == 3) printf("%d\n",Rank(T,x)+1);
		if (op == 4) printf("%d\n",Select(T,x));
		if (op == 5) printf("%d\n",Pred(T,x));
		if (op == 6) printf("%d\n",Succ(T,x));
	}
	return 0;
}



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值