【洛谷P2596】【ZJOI2006】—书架(FHQ_Treap)
考虑到每个点需要维护一个和一个分别表示在书架内的排名和编号
我们再记录一个表示编号的书的排名
考虑以为优先级建
对应5种操作:
1:把先删去再将排名设成一个最小的数插入
2:把删去后把排名设成一个最大数插入
3:把和提出来交换一下他们的和,再交换一下就可以了
4:求的排名
5:求第大,维护一下就可以了
都是平衡树常规操作
调了40多分钟发现写丑了,也是没谁了
#include<bits/stdc++.h>
using namespace std;
inline int read(){
char ch=getchar();
int res=0,f=1;
while(!isdigit(ch)){if(ch=='-')f=-f;ch=getchar();}
while(isdigit(ch))res=(res<<3)+(res<<1)+(ch^48),ch=getchar();
return res*f;
}
const int N=500006;
int siz[N],son[N][2],num[N],val[N],tot,key[N],to[N],seed,rt,n,m,mn,mx;
#define lc(u) son[u][0]
#define rc(u) son[u][1]
inline int rnd(){
return ((rand()*1ll)<<15)%1000000000;
}
inline int addnode(int x,int p){
siz[++tot]=1,val[tot]=x,num[tot]=p,key[tot]=rnd();
lc(tot)=rc(tot)=0;return tot;
}
inline int pushup(int u){
siz[u]=siz[lc(u)]+siz[rc(u)]+1;
}
inline void split(int u,int &a,int &b,int k){
if(u==0){
a=b=0;return;
}
if(val[u]<=k){
a=u,split(rc(u),rc(a),b,k);
}
else {
b=u,split(lc(u),a,lc(b),k);
}
pushup(u);
}
inline void merge(int &u,int a,int b){
if(!a||!b){
u=a+b;return;
}
if(key[a]<key[b])u=a,merge(rc(u),rc(a),b);
else u=b,merge(lc(u),a,lc(b));
pushup(u);
}
inline int find(int x,int k){
while(siz[lc(x)]+1!=k){
if(siz[lc(x)]>=k)
x=lc(x);
else k-=siz[lc(x)]+1,x=rc(x);
}
return x;
}
inline void insert(int k,int p){
int r1=0,r2=0,u;
u=addnode(k,p);
split(rt,r1,r2,k);
merge(r1,r1,u);
merge(rt,r1,r2);
}
inline void delet(int x){
int r1=0,r2=0,r3=0;
split(rt,r1,r2,x);
split(r1,r1,r3,x-1);
merge(r3,lc(r3),rc(r3));
merge(r1,r1,r3);
merge(rt,r1,r2);
}
inline int getrk(int k){
int r1=0,r2=0;
split(rt,r1,r2,k-1);
int res=siz[r1]+1;
merge(rt,r1,r2);
return res;
}
inline int getval(int k){
return num[find(rt,k)];
}
inline int pre(int k){
int r1=0,r2=0;
split(rt,r1,r2,k-1);
int u=find(r1,siz[r1]);merge(rt,r1,r2);
return u;
}
inline int nxt(int k){
int r1=0,r2=0;
split(rt,r1,r2,k);
int u=find(r2,1);merge(rt,r1,r2);
return u;
}
char op[10];
int main(){
srand(time(NULL));
n=read(),m=read();
mx=n,mn=1;
for(int i=1;i<=n;i++){
int k=read();insert(i,k),to[k]=i;
}
for(int i=1;i<=m;i++){
scanf("%s",op);int u=read();
switch(op[0]){
case 'T':{
delet(to[u]),to[u]=--mn;
insert(to[u],u);
break;
}
case 'B':{
delet(to[u]),to[u]=++mx;
insert(to[u],u);
break;
}
case 'I':{
int k=read(),p,now;
if(k==0)break;
if(k==-1)p=pre(to[u]),now=nxt(to[num[p]]);
else if(k==1)p=nxt(to[u]),now=pre(to[num[p]]);
swap(to[num[p]],to[u]),swap(num[p],num[now]);
break;
}
case 'A':{
cout<<getrk(to[u])-1<<'\n';
break;
}
case 'Q':{
cout<<getval(u)<<'\n';
break;
}
}
}
}