这题90%以上的人做法为裸的平衡树,实际上根本没必要还常数大,最好的方法是二分+树状数组。具体做法是,开3倍内存,初始把中间n位赋值为1。对于每个操作:1&2、删除该位,将其丢在头/尾(开三倍内存的原因)。3、插入时直接二分查询第ask(x)+y位,换一下即可。4、直接查询。5、二分查询。复杂度O(nlog2n)

#include<bits/stdc++.h> using namespace std; const int N=240010; int n,m,a[N],id[N],c[N]; void add(int x,int v){while(x<=2*m+n)c[x]+=v,x+=x&-x;} int ask(int x){int ret=0;while(x)ret+=c[x],x-=x&-x;return ret;} int find(int x) { int l=1,r=2*m+n,mid,pos=2*m+n; while(l<=r) { mid=l+r>>1; if(ask(mid)>=x)pos=mid,r=mid-1; else l=mid+1; } return pos; } int main() { scanf("%d%d",&n,&m); for(int i=1,x;i<=n;i++)scanf("%d",&a[i+m]),id[a[i+m]]=i+m,add(i+m,1); for(int i=1;i<=m;i++) { char str[10];int x,y,t,pos,tmp; scanf("%s%d",str,&x); if(str[0]=='T')pos=find(1),add(id[x],-1),add(pos-1,1),id[x]=pos-1,a[id[x]]=x; if(str[0]=='B')pos=find(n),add(id[x],-1),add(pos+1,1),id[x]=pos+1,a[id[x]]=x; if(str[0]=='I') { scanf("%d",&y); if(!y)continue; pos=find(ask(id[x])+y),tmp=a[pos]; swap(a[pos],a[id[x]]),swap(id[x],id[tmp]); } if(str[0]=='A')printf("%d ",ask(id[x])-1); if(str[0]=='Q')printf("%d ",a[find(x)]); } }