样例没有过,输出结果为
-2147483647
644985
-2147483647
不过第一个点A了(?)
#include <bits/stdc++.h>
using namespace std;
int n,opt,x;
struct Treap_Node
{
int ls,rs; //左子树下标、右子树下标
int k,w; //下标、权值
int cnt; //元素重复次数
int size; //子树大小
} Treap[100005];
int root,Treap_size;
int New(int val)
{
Treap_size++;
Treap[Treap_size].k=val;
Treap[Treap_size].w=rand();
Treap[Treap_size].cnt=Treap[Treap_size].size=1;
return Treap_size;
}
void update(int rt)
{
Treap[rt].size=Treap[Treap[rt].ls].size+Treap[Treap[rt].rs].size+Treap[rt].cnt;
} //.size改为了.cnt
void build()
{
root=New(-INT_MAX);
Treap[1].rs=New(INT_MAX);;
update(root);
}
void lrotate(int &rt)
{
int rs=Treap[rt].rs;
Treap[rt].rs=Treap[rs].ls;
Treap[rs].ls=rt;
rt=rs;
update(Treap[rt].ls);
update(rt);
}
void rrotate(int &rt)
{
int ls=Treap[rt].ls;
Treap[rt].ls=Treap[ls].rs;
Treap[ls].rs=rt;
rt=ls;
update(Treap[rt].rs);
update(rt);
}
void insert(int &rt,int val)
{
if (rt==0)
{
rt=New(val);
return;
}
if (Treap[rt].k==val)
{
Treap[rt].cnt++;
//update(rt);
//return;
}
/*if (Treap[rt].k>val)
{
insert(Treap[rt].ls,val);
if (Treap[rt].w<Treap[Treap[rt].ls].w) //
rrotate(rt);
}*/
else
{
/*insert(Treap[rt].rs,val);
if (Treap[rt].w<Treap[Treap[rt].rs].w) //
lrotate(rt);*/
if (Treap[rt].k<val)
{
insert(Treap[rt].ls,val);
if (Treap[rt].w<Treap[Treap[rt].ls].w)
{
rrotate(rt);
}
}
else
{
insert(Treap[rt].rs,val);
if (Treap[rt].w<Treap[Treap[rt].rs].w)
{
lrotate(rt);
}
}
}
update(rt);
return;
}
void del(int &rt,int val)
{
if (rt==0) return;
if (Treap[rt].k==val)
{
if (Treap[rt].cnt>1)
{
Treap[rt].cnt--;
update(rt);
return;
}
if (Treap[rt].ls || Treap[rt].rs)
{
/*else*/ if (Treap[rt].rs==0 || Treap[Treap[rt].ls].cnt>Treap[Treap[rt].rs].cnt)
{
rrotate(rt);
del(Treap[rt].rs,val);
}
//if (Treap[rt].ls==0 || Treap[Treap[rt].ls].w>Treap[Treap[rt].rs].w)
else
{
lrotate(rt);
del(Treap[rt].ls,val);
}
}
else rt=0;
return;
}
if (Treap[rt].k>val) del(Treap[rt].ls,val);
else del(Treap[rt].rs,val);
update(rt);
}
int getrank(int rt,int val)
{
if (rt==0) return 0;
if (Treap[rt].k==val) return Treap[Treap[rt].ls].size+1;
else if (Treap[rt].k>val) return getrank(Treap[rt].ls,val);
else return getrank(Treap[rt].rs,val)+Treap[Treap[rt].ls].size+Treap[rt].cnt;
//else if (Treap[rt].k<val) return getrank(Treap[rt].rs,val);
} //由h:140修改为h:139
int getranx(int rt,int ranx)
{
if (rt==0) return INT_MAX;
if (Treap[Treap[rt].ls].size>=ranx)
return getranx(Treap[rt].ls,ranx);
else if (Treap[Treap[rt].ls].size+Treap[rt].cnt>=ranx)
return Treap[rt].k;
else return getranx(Treap[rt].rs,ranx-Treap[Treap[rt].ls].size-Treap[rt].cnt);
}
int getpre(int val)
{
int pre;
int rt=root;
while (rt)
{
/*if (Treap[rt].k==val)
{
if (Treap[rt].ls>0)
{
rt=Treap[rt].ls;
while (Treap[rt].ls>0)
rt=Treap[rt].rs;
ans=rt;
}
break;
}
if (Treap[rt].k<val && Treap[rt].k>Treap[ans].k)
ans=rt;
if (Treap[rt].k>val) rt=Treap[rt].ls;
else rt=Treap[rt].rs;*/
if (Treap[rt].k<val)
{
pre=Treap[rt].k;
rt=Treap[rt].rs;
}
else rt=Treap[rt].ls;
}
//return Treap[ans].k;
return pre;
}
int getnext(int val)
{
int next;
int rt=root;
while (rt)
{
/*if (Treap[rt].k==val)
{
if (Treap[rt].rs>0)
{
rt=Treap[rt].rs;
while (Treap[rt].rs>0)
rt=Treap[rt].ls;
ans=rt;
}
break;
}
if (Treap[rt].k<val && Treap[rt].k>Treap[ans].k)
ans=rt;
if (Treap[rt].k>val) rt=Treap[rt].rs;
else rt=Treap[rt].ls;*/
if (Treap[rt].k>val)
{
next=Treap[rt].k;
rt=Treap[rt].ls;
}
else rt=Treap[rt].rs;
}
//return Treap[ans].k;
return next;
}
int main()
{
build(); //先建个有边界的空树,或言初始化
scanf("%d",&n);
while (n--)
{
scanf("%d %d",&opt,&x);
if (opt==1) insert(root,x);
else if (opt==2) del(root,x);
else if (opt==3) printf("%d\n",getrank(root,x)-1);//Build的时候已经插入了两个极值边界,故会多出一个比x小的数,所以要减一
else if (opt==4) printf("%d\n",getranx(root,x+1));//Build的时候已经插入了两个极值边界,故查询的时候要把最小极值也考虑上
else if (opt==5) printf("%d\n",getpre(x));
else if (opt==6) printf("%d\n",getnext(x));
}
return 0;
}
旋转型Treap的思路应该都差不多吧?不过代码实验似乎有挺多细节都不一样的。
我这个第一遍写的代码的样例输出是:
2147483647
2147483647
492737
之后翻了挺多教程、题解,最后大体按照天上一颗蛋 大佬的题解 进行修改的,被注释掉的是最开始写的,现在这个就是修改过的,不过输出还是不对,希望能有大佬帮忙看一下,谢谢啦!