1. 程式人生 > >【BZOJ1861】書架(ZJOI2006)-平衡樹復健題

【BZOJ1861】書架(ZJOI2006)-平衡樹復健題

測試地址:書架
做法:好久沒做平衡樹的題了,結果一道水題寫了一晚上……唉……
這一道題需要用到平衡樹。
這一題可以按書的編號建點,然後給每個點附上一個優先值,那麼按優先值從小到大排序就是當前書架上書的順序了。題目中的幾個操作就可以寫成這樣:
Top和Bottom操作:將一個點的優先值賦成比當前所有點優先值都小(或者都大),然後重新插入該點。
Insert操作:將相鄰兩個點的優先值交換,然後重新插入。
Ask和Query操作:經典的求某點排名或求某排名的點的操作。
以上這些操作就明顯可以用平衡樹維護了。
以下是本人程式碼:

#include <cstdio>
#include <cstdlib>
#include <cstring> #include <iostream> #include <algorithm> #define N 100000 using namespace std; int n,m,nowmn,nowmx,rt; int val[N+10],siz[N+10],ch[N+10][2],fa[N+10]; char op[15]; void debug() { printf("===debug===\n"); for(int i=1;i<=n+2;i++) printf("%d %d %d %d\n",ch[i][0
],ch[i][1],fa[i],siz[i]); } void pushup(int v) { siz[v]=siz[ch[v][0]]+siz[ch[v][1]]+1; } void rotate(int x,bool f) { int y=fa[x]; ch[y][!f]=ch[x][f]; fa[ch[x][f]]=y; ch[x][f]=y; if (fa[y]) ch[fa[y]][ch[fa[y]][1]==y]=x; fa[x]=fa[y]; fa[y]=x; pushup(y); } void Splay(int
x,int goal) { while(fa[x]!=goal) { if (fa[fa[x]]==goal) rotate(x,ch[fa[x]][0]==x); else { int y=fa[x],z=fa[fa[x]]; bool f=(ch[y][1]==x); if (ch[z][f]==y) rotate(y,!f),rotate(x,!f); else rotate(x,!f),rotate(x,f); } } pushup(x); if (!goal) rt=x; } void insert(int &v,int now,int f) { if (!v) { v=now; fa[v]=f; siz[v]=1; ch[v][0]=ch[v][1]=0; Splay(v,0); return; } siz[v]++; insert(ch[v][val[now]>val[v]],now,v); } int rank(int v) { Splay(v,0); return siz[ch[v][0]]+1; } int query(int x) { int v=rt; while(siz[ch[v][0]]+1!=x) { if (siz[ch[v][0]]+1<x) x-=siz[ch[v][0]]+1,v=ch[v][1]; else v=ch[v][0]; } return v; } void Delete(int v) { int r=rank(v); Splay(query(r-1),0); Splay(query(r+1),rt); siz[rt]--,siz[ch[rt][1]]--; ch[ch[rt][1]][0]=0; } int main() { scanf("%d%d",&n,&m); for(int i=1;i<=n;i++) { int x; scanf("%d",&x); val[x]=i; } rt=n+1; nowmn=1,nowmx=n; fa[n+1]=0,siz[n+1]=2,ch[n+1][0]=0,ch[n+1][1]=n+2,val[n+1]=-10000000; fa[n+2]=n+1,siz[n+2]=1,ch[n+2][0]=ch[n+2][1]=0,val[n+2]=10000000; siz[0]=0; for(int i=1;i<=n;i++) insert(rt,i,0); for(int i=1;i<=m;i++) { int s,t; scanf("%s",op); scanf("%d",&s); if (op[0]=='T') { Delete(s); val[s]=--nowmn; insert(rt,s,0); } if (op[0]=='B') { Delete(s); val[s]=++nowmx; insert(rt,s,0); } if (op[0]=='I') { scanf("%d",&t); if (!t) {Splay(s,0);continue;} int x=query(rank(s)+t); Delete(s); Delete(x); swap(val[s],val[x]); insert(rt,s,0); insert(rt,x,0); } if (op[0]=='A') { printf("%d\n",rank(s)-2); } if (op[0]=='Q') { printf("%d\n",t=query(s+1)); Splay(t,0); } } return 0; }