这个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;
}