Treap 60pts WA求调qwq
查看原帖
Treap 60pts WA求调qwq
614725
masonpop楼主2022/7/25 07:56

这个treap样例过了,交上去中间5个点全WA,不知道哪里错了,求调!

#include <bits/stdc++.h>
using namespace std;
#define int long long
const int maxn=1000010;
const int inf=1e9+7;
int t;
int ch[maxn][2];//0左儿子,1右儿子
int val[maxn],dat[maxn];//节点权值,优先级(随机的)
int num[maxn],siz[maxn];//相同数个数,子树大小
int tot,root;
inline int new_node(int v)//新建节点
{
	val[++tot]=v;
	siz[tot]=1;//目前为叶子,大小为1 
	dat[tot]=rand();//随机优先级
	num[tot]=1;//只有一个
	return tot;//返回编号 
} 
inline void update(int p)//更新,类似线段树
{
	siz[p]=siz[ch[p][0]]+siz[ch[p][1]]+num[p];//替换 
} 
inline void build()//建树
{
	root=new_node(-inf),ch[root][1]=new_node(inf);//初始化极大值
	update(root);//更新 
} 
inline void spin(int &id,int dir)//旋转的点,方向(0左旋,1右旋) 
{
	//下面以左旋为例。
	//首先,自己右儿子变为自己原来右儿子的左儿子。
	//然后,原来自己右儿子变为自己父亲
	int right=ch[id][dir^1];//右旋同理
	ch[id][dir^1]=ch[right][dir];//根据注释理解一下吧~
	ch[right][dir]=id;//上提
	id=right;//更新根节点
	update(ch[id][dir]);
	update(id);//更新 
} 
inline void insert(int &id,int v)//插入
{
	if(!id)//没出现过
	{
		id=new_node(v);//新建
		return; 
	} 
	if(v==val[id])num[id]++;//添加(找到了)
	else
	{
		int dir=((v<val[id])?0:1);//小于插左边,否则插右边
		insert(ch[id][dir],v);//递归插入
		if(dat[ch[id][dir]]>dat[id])spin(id,dir^1);//把下面的转上来
		//注意左旋右边上来,右旋左边上来
		update(id);//更新 
	} 
} 
inline void delet(int &id,int v)//删除
{
	if(!id)return;//不存在 
	if(val[id]==v)//查到了 
	{
		if(num[id]>1)//大于一直接减
		{
			num[id]--;
			update(id);//更新
			return; 
		} 
		if(ch[id][0] || ch[id][1])//有儿子,要处理一下
		{
			if(!ch[id][1] || dat[ch[id][0]]>dat[ch[id][1]])//左边优先级更大,转上来 
			{
				spin(id,1);//右旋 
				delet(ch[id][1],v);//递归删除 
			} 
			else
			{
				spin(id,0);//反之左旋
				delet(ch[id][0],v);//递归删除 
			}
			update(id);//更新 
		} 
		else id=0;//叶子结点直接删除
		return; 
	}
	(v<val[id])?delet(ch[id][0],v):delet(ch[id][1],v);//按照BST规则删除 
	update(id);
} 
inline int get_rank(int id,int v)//求排名
{
	if(!id)return 0;//不存在
	if(v==val[id])return siz[ch[id][0]]+1;//正好为根
	else if(v<val[id])return get_rank(ch[id][0],v);//左边递归
	else return siz[ch[id][0]]+num[id]+get_rank(ch[id][1],v);//继续搜索 
} 
inline int get_val(int id,int rank)//已知排名求数
{
	if(!id)return inf;//不存在
	if(rank<=siz[ch[id][0]])return get_val(ch[id][0],rank);//左边 
	else if(rank<=(siz[ch[id][0]]+num[id]))return val[id];//就是根
	else return get_val(ch[id][1],rank-siz[ch[id][0]]-num[id]);//右边 
} 
int get_pre(int v)
{
	int id = root,pre;//循环
	while(id)//存在 
	{
		if(val[id]<v)
		{
			pre=val[id];//更新 
			id=ch[id][1];//向右 
		}
		else id=ch[id][0];//左边 
	}
	return pre;
}
int get_suf(int v)
{
	int id = root,pre;//循环
	while(id)//存在 
	{
		if(val[id]>v)
		{
			pre=val[id];//更新 
			id=ch[id][0];//向左 
		}
		else id=ch[id][1];//右边 
	}
	return pre;
}
signed main()
{
	build();
	scanf("%lld",&t);
	while(t--)//直接回答即可 
	{
		int opt,x;
		scanf("%lld%lld",&opt,&x);
		if(opt==1)insert(root,x);//插入 
		else if(opt==2)delet(root,x);//删除
		else if(opt==3)printf("%lld\n",get_rank(root,x)-1);//注意去掉我们手动加的-inf
	    else if(opt==4)printf("%lld\n",get_val(root,x+1));//同理
		else if(opt==5)printf("%lld\n",get_pre(x));
		else printf("%lld\n",get_suf(x)); 
	}
	return 0;
}

记录

2022/7/25 07:56
加载中...