1. 程式人生 > >解題:ZJOI 2006 書架

解題:ZJOI 2006 書架

aps query pla opened div roo gif play -s

題面

學習了如何在維護序列的平衡樹上查找某個數:按初始的順序定個權值,然後每次找那個權值的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\n",pos-1); 99 else 100 { 101 Split(root,x,z,rd),Split(x,x,y,rd-1); 102 printf("%d\n",val[y]); 103 root=Merge(Merge(x,y),z); 104 } 105 } 106 return 0; 107 }
View Code

解題:ZJOI 2006 書架