社区讨论

蒟蒻的FHQ Treap板子求调

P3369【模板】普通平衡树参与者 2已保存回复 3

讨论操作

快速查看讨论及其快照的属性,并进行相关操作。

当前回复
3 条
当前快照
1 份
快照标识符
@lo2iv3u5
此快照首次捕获于
2023/10/23 14:33
2 年前
此快照最后确认于
2023/10/23 14:33
2 年前
查看原帖
顺便询问一下 rand() 函数头文件是什么(感觉查到的这个不是很常用的样子?)
蒟蒻的注释特别多(。)方便自己理解罢了。
CPP
#include<cstdio>
#include<iostream>
#include<stdlib.h>
#define int long long
const int N=1e5+10;
int n;
struct Tree{
	int d,siz,L,R,ran;//ran优先性,保证结构不退化 
}t[N];
int tot=0,root=1;
void New(int v)
{
	t[++tot].d=v;
	t[tot].L=t[tot].R=0; 
	t[tot].siz=1;
	t[tot].ran=rand();
}
void pushup(int p)
{
	t[p].siz=t[t[p].L].siz+t[t[p].R].siz+1;
}
void Split(int p,int &l,int &r,int x)
{
	if (!p)
	{
		l=r=0;
		return;
	}
	if (t[p].d<=x)//小于等于放左子树 
	{
		l=p;
		Split(t[p].R,t[p].R,r,x);
	}
	else
	{
		r=p;
		Split(t[p].L,l,t[p].L,x);
	}
	pushup(p);
}
int Merge(int l,int r)//返回根节点 
{
	if (!l||!r) return l+r;
	if (t[l].ran<=t[r].ran)
	{
		t[r].L=Merge(l,t[r].L);
		pushup(r);
		return r;
	}
	else
	{
		t[l].R=Merge(t[l].R,r);
		pushup(l);
		return l;
	}
}
void Insert(int x)
{
	int l,r;
	Split(root,l,r,x);
	New(x);
	int l1=Merge(l,tot);
	root=Merge(l1,r);
}
void Delete(int x)
{
	int l,r,p;
	Split(root,l,r,x);//左儿子带x,右儿子不带 
	Split(l,l,p,x-1);//分出左儿子中的x树 
	p=Merge(t[p].L,t[p].R);//合并x树的左右儿子,相当于删掉根节点 
	root=Merge(Merge(l,p),r);
}
int Rank(int x)//查询数x的排名 
{
	int l,r;
	Split(root,l,r,x-1);//左子树不包括x 
	int k=t[l].siz;
	root=Merge(l,r);
	return k+1;
}
int k_th(int p,int k)//查询排名为k的数
{
	if (t[t[p].L].siz+1==k) return p;//返回的是编号 
	if (t[t[p].L].siz>=k) return k_th(t[p].L,k);//在左子树 
	else return k_th(t[p].R,k-t[t[p].L].siz-1);//在右子树 
}
int pre(int x)//前驱 
{
	int l,r;
	Split(root,l,r,x-1);//左子树最大的是x-1 
	int p=k_th(l,t[l].siz);//查找左子树最大的(最右 
	root=Merge(l,r);
	return p;
} 
int suc(int x)//后继 
{
	int l,r;
	Split(root,l,r,x);//右子树最小的是x+1 
	int p=k_th(r,1);//查询右子树最小的(最左 
	root=Merge(l,r);
	return p;
}
signed main()
{
	scanf("%lld",&n);
	while (n--)
	{
		int op,x;
		scanf("%lld%lld",&op,&x);
		if (op==1) Insert(x);
		else if (op==2) Delete(x);
		else if (op==3) printf("%lld\n",Rank(x));
		else if (op==4) printf("%lld\n",t[k_th(root,x)].d);
		else if (op==5) printf("%lld\n",t[pre(x)].d);
		else printf("%lld\n",t[suc(x)].d);
	}
	return 0;
}

回复

3 条回复,欢迎继续交流。

正在加载回复...