fhq treap
开个minn
和maxn
作排序标准
置顶就更新val=--minn
,垫底就更新val=++maxn
改变位置就相当于找前驱后继swap(val1,val2)
找排名为k
的编号就是二叉查找树的模板
找编号为k
前面的书个数就拆树取左边的siz
#include"cstdio"
#include"cstring"
#include"iostream"
#include"algorithm"
#include"ctime"
using namespace std;
const int MAXN=8e4+5;
int n,m,cnt,minn,root,maxn;
int siz[MAXN],sn[MAXN][2];
int rev[MAXN],val[MAXN];
char ch[16];
int cret(int x,int v)
{
siz[x]=1;
val[x]=v;
rev[x]=rand();
sn[x][0]=sn[x][1]=0;
return x;
}
int un(int x,int y)
{
if(!x||!y) return x|y;
if(rev[x]<rev[y]){
sn[x][1]=un(sn[x][1],y);
siz[x]=siz[sn[x][0]]+siz[sn[x][1]]+1;
return x;
}sn[y][0]=un(x,sn[y][0]);
siz[y]=siz[sn[y][0]]+siz[sn[y][1]]+1;
return y;
}
void dro(int k,int v,int &x,int &y)
{
if(!k){x=y=0;return;}
if(val[k]<=v) x=k,dro(sn[k][1],v,sn[k][1],y);
else y=k,dro(sn[k][0],v,x,sn[k][0]);
siz[k]=siz[sn[k][0]]+siz[sn[k][1]]+1;
return;
}
int rnk(int k,int v)
{
if(v<=siz[sn[k][0]]) return rnk(sn[k][0],v);
if(v==siz[sn[k][0]]+1) return k;
return rnk(sn[k][1],v-siz[sn[k][0]]-1);
}
void debug()
{
for(int i=1;i<=n;++i) printf("%d ",rnk(root,i));
puts("");
}
void Tp()
{
int v,x,y,z;scanf("%d",&v);
dro(root,val[v],x,z),dro(x,val[v]-1,x,y);
y=un(sn[y][0],sn[y][1]);root=un(un(x,y),z);
--minn;cret(v,minn);
dro(root,val[v],x,y);
root=un(un(x,v),y);
return;
}
void Bt()
{
int v,x,y,z;scanf("%d",&v);
dro(root,val[v],x,z),dro(x,val[v]-1,x,y);
y=un(sn[y][0],sn[y][1]);root=un(un(x,y),z);
++maxn;cret(v,maxn);
dro(root,val[v],x,y);
root=un(un(x,v),y);
return;
}
void del(int v)
{
int x,y,z;
dro(root,val[v],x,z);dro(x,val[v]-1,x,y);
y=un(sn[y][0],sn[y][1]);
root=un(un(x,y),z);
return;
}
void Ins()
{
int v,u,x,y,tmp;scanf("%d%d",&v,&u);
if(!u) return;
if(u==1) dro(root,val[v],x,y),tmp=rnk(y,1),root=un(x,y);
else dro(root,val[v]-1,x,y),tmp=rnk(x,siz[x]),root=un(x,y);
int v1=val[v],v2=val[tmp];
del(v);del(tmp);
dro(root,v1,x,y);root=un(un(x,cret(tmp,v1)),y);
dro(root,v2,x,y);root=un(un(x,cret(v,v2)),y);
return;
}
void As()
{
int v,x,y;scanf("%d",&v);
dro(root,val[v]-1,x,y);
printf("%d
",siz[x]);
root=un(x,y);
return;
}
void Cas()
{
int v,x,y;scanf("%d",&v);
printf("%d
",rnk(root,v));
return;
}
int main()
{
scanf("%d%d",&n,&m);maxn=n;
for(int i=1;i<=n;++i){
int v,x,y;scanf("%d",&v);
dro(root,i,x,y);
root=un(un(x,cret(v,i)),y);
}while(m--){
scanf("%s",ch+1);
if(ch[1]=='T') Tp();
else if(ch[1]=='B') Bt();
else if(ch[1]=='I') Ins();
else if(ch[1]=='A') As();
else Cas();
}return 0;
}