解题:ZJOI 2006 书架
Posted ydnhaha
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了解题:ZJOI 2006 书架相关的知识,希望对你有一定的参考价值。
学习了如何在维护序列的平衡树上查找某个数:按初始的顺序定个权值,然后每次找那个权值的DFS序即可。具体实现就是不停往上跳,然后是父亲的右儿子就加上父亲的左儿子,剩下的就是继续熟悉无旋树堆
1 #include<cstdio> 2 #include<cstring> 3 #include<algorithm> 4 using namespace std; 5 const int N=100005; 6 int num[N],val[N],siz[N],anc[N],son[N][2],rnk[N]; 7 int n,m,w,x,y,z,rd,re,tot,pos,root; char ch[10]; 8 void Pushup(int nde) 9 { 10 siz[nde]=siz[son[nde][0]]+siz[son[nde][1]]+1; 11 if(son[nde][0]) anc[son[nde][0]]=nde; 12 if(son[nde][1]) anc[son[nde][1]]=nde; 13 } 14 int Create(int tsk) 15 { 16 siz[++tot]=1; 17 val[tot]=tsk; 18 num[tsk]=tot; 19 rnk[tot]=rand(); 20 return tot; 21 } 22 int Merge(int x,int y) 23 { 24 if(!x||!y) return x+y; 25 else if(rnk[x]<=rnk[y]) 26 { 27 son[x][1]=Merge(son[x][1],y); 28 Pushup(x); return x; 29 } 30 else 31 { 32 son[y][0]=Merge(x,son[y][0]); 33 Pushup(y); return y; 34 } 35 } 36 void Split(int nde,int &x,int &y,int tsk) 37 { 38 if(!nde) x=y=0; 39 else 40 { 41 if(siz[son[nde][0]]<tsk) 42 x=nde,Split(son[nde][1],son[nde][1],y,tsk-siz[son[nde][0]]-1); 43 else 44 y=nde,Split(son[nde][0],x,son[nde][0],tsk); 45 Pushup(nde); 46 } 47 } 48 int Query(int nde) 49 { 50 int ret=siz[son[nde][0]]+1; 51 while(anc[nde]) { 52 if(nde==son[anc[nde]][1]) 53 ret+=siz[son[anc[nde]][0]]+1; 54 nde=anc[nde]; 55 } 56 return ret; 57 } 58 void DFS(int nde) 59 { 60 if(son[nde][0]) DFS(son[nde][0]); 61 printf("->%d",val[nde]); 62 if(son[nde][1]) DFS(son[nde][1]); 63 } 64 int main() 65 { 66 srand(20020513); 67 scanf("%d%d",&n,&m); 68 for(int i=1;i<=n;i++) 69 scanf("%d",&rd),root=Merge(root,Create(rd)); 70 while(m--) 71 { 72 scanf("%s%d",ch,&rd),pos=Query(num[rd]); 73 if(ch[0]==‘T‘) 74 { 75 Split(root,x,z,pos),Split(x,x,y,pos-1); 76 root=Merge(Merge(y,x),z); 77 } 78 else if(ch[0]==‘B‘) 79 { 80 Split(root,x,z,pos),Split(x,x,y,pos-1); 81 root=Merge(Merge(x,z),y); 82 } 83 else if(ch[0]==‘I‘) 84 { 85 scanf("%d",&re); 86 if(re==-1) 87 { 88 Split(root,w,z,pos),Split(w,w,y,pos-1); 89 Split(w,w,x,pos-2); root=Merge(Merge(Merge(w,y),x),z); 90 } 91 else if(re==1) 92 { 93 Split(root,y,z,pos+1),Split(y,x,y,pos); 94 Split(x,w,x,pos-1); root=Merge(Merge(Merge(w,y),x),z); 95 } 96 } 97 else if(ch[0]==‘A‘) 98 printf("%d ",pos-1); 99 else 100 { 101 Split(root,x,z,rd),Split(x,x,y,rd-1); 102 printf("%d ",val[y]); 103 root=Merge(Merge(x,y),z); 104 } 105 } 106 return 0; 107 }
以上是关于解题:ZJOI 2006 书架的主要内容,如果未能解决你的问题,请参考以下文章
[bzoj1861][Zjoi2006]Book 书架_非旋转Treap