题目
平衡树裸题。。按层数随便赋个值表示相对关系,然后查找排名就好了。(我依然调一年)…
然而这题线段树做法比较有趣。
空间开足够对于每次top和bot操作要新开空间。数组记录编号为s的书在线段树上的位置。
线段树上维护那段区间有没有书。
然后对于top和bot操作。。二分一直跳到没有书的第一个为0的点。对于ins操作。交换相邻点。
ask查询区间和(前缀)。
query二分一直找到那一本书(靠区间和来找)。
然而我并没有写线段树做法。
#include<bits/stdc++.h>
using namespace std;
const int MAXN=8e4+5;
const int INF=1e9+7;
#define mp make_pair
typedef pair<int,int>par;
struct treap{
int rt,cnt;
int lson[MAXN],rson[MAXN],prio[MAXN],size[MAXN],w[MAXN];
inline void pushup(int p){size[p]=size[lson[p]]+size[rson[p]]+1;}
inline par split(int p,int x){
if(!x)return mp(0,p);
int l=lson[p],r=rson[p];
if(x<=size[l]){
par tem=split(l,x);
lson[p]=tem.second;pushup(p);return mp(tem.first,p);
}
par tem=split(r,x-size[l]-1);
rson[p]=tem.first;pushup(p);return mp(p,tem.second);
}
inline int merge(int x,int y){
if(!x){pushup(y);return y;}
if(!y){pushup(x);return x;}
if(prio[x]<prio[y]){rson[x]=merge(rson[x],y);pushup(x);return x;}
lson[y]=merge(x,lson[y]);pushup(y);return y;
}
inline void newnode(int p,int x){
lson[p]=rson[p]=0;prio[p]=rand();size[p]=1;w[p]=x;
}
}T;
void dfs(int p){
if(!p)return;
dfs(T.lson[p]);
printf("%d ",T.w[p]);
dfs(T.rson[p]);
}
int where[MAXN],sta[MAXN],xj,sj;
int build(int n){
int tmp,tp=0;
for(int i=1;i<=n;i++){
int pre=0;
scanf("%d",&tmp);
T.newnode(++T.cnt,tmp);
where[tmp]=T.cnt;
while(tp&&T.prio[sta[tp]]>T.prio[T.cnt]){
pre=sta[tp--];T.pushup(pre);
}
if(tp)T.rson[sta[tp]]=T.cnt;
T.lson[T.cnt]=pre;
sta[++tp]=T.cnt;
}
while(tp)T.pushup(tp--);
xj=1;sj=n;
return sta[1];
}
int queryrank(int x){
int cp=where[x],tmp=T.rt,ans=0;
// cout<<cp<<"okokok ";
// cout<<T.size[T.lson[T.rt]]+1;
while(where[T.w[tmp]]!=cp){
// cout<<tmp<<":"<<where[tmp]<<endl;
if(cp>=where[T.w[tmp]])ans+=T.size[T.lson[tmp]]+1;
else {tmp=T.lson[tmp];continue;}
if(cp>where[T.w[tmp]])tmp=T.rson[tmp];
}
ans+=T.size[T.lson[tmp]]+1;
// cout<<" "<<T.w[tmp]<<"sasa sasasa sasa";cout<<ans<<endl;
return ans;
}
void top(){
int tmp;
scanf("%d",&tmp);
int a=queryrank(tmp);
par tem1=T.split(T.rt,a);
par tem2=T.split(tem1.first,a-1);
// cout<<a<<"okok";
where[T.w[tem2.second]]=--xj;
T.rt=T.merge(T.merge(tem2.second,tem2.first),tem1.second);
// dfs(T.rt);
}
void bot(){
int tmp;
scanf("%d",&tmp);
int a=queryrank(tmp);
par tem1=T.split(T.rt,a);
par tem2=T.split(tem1.first,a-1);
where[T.w[tem2.second]]=++sj;
T.rt=T.merge(T.merge(tem2.first,tem1.second),tem2.second);
// dfs(T.rt);
}
void ins(){
int tmp,tmp2;
scanf("%d%d",&tmp,&tmp2);
if(tmp2==0)return;
int a=queryrank(tmp);
if(tmp2==1){
par tem1=T.split(T.rt,a+1);
par tem2=T.split(tem1.first,a-1);//t2 second 2个
par tem3=T.split(tem2.second,1);
swap(where[T.w[tem3.first]],where[T.w[tem3.second]]);
T.rt=T.merge(T.merge(tem2.first,T.merge(tem3.second,tem3.first)),tem1.second);
}
else {
par tem1=T.split(T.rt,a);
par tem2=T.split(tem1.first,a-2);//t2 second 2个
par tem3=T.split(tem2.second,1);
swap(where[T.w[tem3.first]],where[T.w[tem3.second]]);
T.rt=T.merge(T.merge(tem2.first,T.merge(tem3.second,tem3.first)),tem1.second);
}
// dfs(T.rt);
}
void ask(){
int tmp;
scanf("%d",&tmp);
printf("%d\n",queryrank(tmp)-1);
}
void query(){
int tmp;
scanf("%d",&tmp);
par tem1=T.split(T.rt,tmp-1);
par tem2=T.split(tem1.second,1);
printf("%d\n",T.w[tem2.first]);
T.rt=T.merge(tem1.first,T.merge(tem2.first,tem2.second));
}
int main(){
srand(19260817);
char tem[15];
int n,m;
T.cnt=0;
scanf("%d%d",&n,&m);
T.rt=build(n);
// cout<<T.w[T.rt];
// cout<<where[T.w[T.rt]];
for(int i=1;i<=m;i++){
scanf("%s",tem);
if(tem[0]=='T')top();
if(tem[0]=='B')bot();
if(tem[0]=='I')ins();
if(tem[0]=='A')ask();
if(tem[0]=='Q')query();
}
return 0;
}