BZOJ 1861 Book 书架 第一份完全凭自己理解手敲的Splay树啊。记念一下
2013-09-09 17:01
453 查看
1861: [Zjoi2006]Book 书架
Time Limit: 4 Sec Memory Limit:64 MB
Submit: 325 Solved: 193
[Submit][Status]
Description
小T有一个很大的书柜。这个书柜的构造有些独特,即书柜里的书是从上至下堆放成一列。她用1到n的正整数给每本书都编了号。 小T在看书的时候,每次取出一本书,看完后放回书柜然后再拿下一本。由于这些书太有吸引力了,所以她看完后常常会忘记原来是放在书柜的什么位置。不过小T的记忆力是非常好的,所以每次放书的时候至少能够将那本书放在拿出来时的位置附近,比如说她拿的时候这本书上面有X本书,那么放回去时这本书上面就只可能有X-1、X或X+1本书。 当然也有特殊情况,比如在看书的时候突然电话响了或者有朋友来访。这时候粗心的小T会随手把书放在书柜里所有书的最上面或者最下面,然后转身离开。久而久之,小T的书柜里的书的顺序就会越来越乱,找到特定的编号的书就变得越来越困难。于是她想请你帮她编写一个图书管理程序,处理她看书时的一些操作,以及回答她的两个提问:(1)编号为X的书在书柜的什么位置;(2)从上到下第i本书的编号是多少。
Input
第一行有两个数n,m,分别表示书的个数以及命令的条数;第二行为n个正整数:第i个数表示初始时从上至下第i个位置放置的书的编号;第三行到m+2行,每行一条命令。命令有5种形式: 1. Top S——表示把编号为S的书房在最上面。 2. Bottom S——表示把编号为S的书房在最下面。 3. Insert S T——T∈{-1,0,1},若编号为S的书上面有X本书,则这条命令表示把这本书放回去后它的上面有X+T本书; 4. Ask S——询问编号为S的书的上面目前有多少本书。5. Query S——询问从上面数起的第S本书的编号。
Input:
10 111
1 3 2 7 5 8 10 4 9 6
Query 3
Top 5
Ask 6
Bottom 3
Ask 3
Top 6
Insert 4 -1
Query 5
Query 2
Ask 2
其实思路没有什么,就是模拟Splay树
// // 1861.cpp // ACM_BZOJ // // Created by ipqhjjybj on 13-9-9. // Copyright (c) 2013年 ipqhjjybj. All rights reserved. // 第一道完全手敲得啊。任重道远。。 // #include <cstdio> #include <cstdlib> #include <map> #include <cstring> using namespace std; #define Key_Tree child[child[root][1]][0] int n; struct SplayTree{ const static int maxn=111111; int n,tot,root; int pre[maxn],size[maxn];//flex[maxn] int child[maxn][2]; int a[maxn]; void Travel(int u){ if(!u) return; printf("u=%d c0=%d c1=%d s0=%d s1=%d\n",u,child[u][0],child[u][1],size[child[u][0]]+size[child[u][1]]); Travel(child[u][0]); Travel(child[u][1]); } void Push_up(int &x){ size[x]=size[child[x][0]]+size[child[x][1]]+1; } void Del_root(){ int t=root; if(child[root][1]){ root=child[root][1]; // printf("root=%d\n",root); Select(1,0); child[root][0]=child[t][0]; if(child[t][0]) pre[child[t][0]]=root; }else root=child[root][0]; pre[root]=0; Push_up(root); child[t][0]=child[t][1]=0;//清空t size[t]=1; } //c==0 左旋 c==1 右旋 inline void Rotate(int x,int c){ int y=pre[x]; //Pushdown(y),Pushdown(x); child[y][!c]=child[x][c]; if(child[x][c]) pre[child[x][c]]=y; pre[x]=pre[y]; if(pre[y]) child[pre[y]][child[pre[y]][1]==y]=x; child[x][c]=y; pre[y]=x; Push_up(y); } void Splay(int x,int f){ //Push_down(x); while(pre[x]!=f){ int y=pre[x],z=pre[y]; //Push_down(z),Push_down(y),Push_down(x); if(pre[pre[x]]==f){ Rotate(x,child[pre[x]][0]==x); }else{ if(child[z][0]==y){ if(child[y][0]==x) Rotate(y,1),Rotate(x,1); else Rotate(x,0),Rotate(x,1); }else{ if(child[y][0]==x) Rotate(x,1),Rotate(x,0); else Rotate(y,0),Rotate(x,0); } } } Push_up(x); if(!f) root=x; } int Select(int k,int f){ int x=root; while(1){ if(k==size[child[x][0]]+1) break; if(k<=size[child[x][0]]) x=child[x][0]; else{ k-=size[child[x][0]]+1; x=child[x][1]; } } Splay(x,f); return x; } //after one number's void Insert(int t,int after){ Select(after,0); int x=Select(after+1,root); Key_Tree=t;//或者child[x][0]=t; pre[t]=x; Push_up(t); Push_up(x); } void Top(int t){ Select(1,0); child[root][0]=t; pre[t]=root; Push_up(t); Push_up(root); } int Find_kth(int k){ int t=root; while(1){ if(size[child[t][0]]+1==k) break; else if(size[child[t][0]]>=k) t=child[t][0]; else k-=size[child[t][0]]+1,t=child[t][1]; } return t; } void Init(int _n){ n=_n; for(int i=1;i<=n;i++) scanf("%d",a+i); memset(child,0,(n+3)*2*sizeof(int)); for(int i=1;i<=n;i++){ pre[i-1]=i; child[i][0]=i-1; size[i]=i; }pre =n+1,child[n+1][0]=n,a[n+1]=n+1,pre[n+1]=0,root=n+1,a[0]=0; size[0]=0,size[n+1]=n+1; child[0][0]=child[0][1]=0; Map.clear(); for(int i=1;i<=n;i++) Map[a[i]]=i; } map<int,int> Map; }spt; void Init(int n){ spt.Init(n); } int Ask(int t){ spt.Splay(t,0); return spt.size[spt.child[t][0]]; } void Top(int t){ spt.Splay(t,0); spt.Del_root(); spt.Top(t); } int Query(int k){ return spt.a[spt.Find_kth(k)]; } void Bottom(int t){ spt.Splay(t,0); spt.Del_root(); spt.Insert(t,n-1); } void Insert(int t,int val){ spt.Splay(t,0); int sz=spt.size[spt.child[t][0]]; sz+=val; if(sz==0){ //个人的函数问题,需要特判 Top(t); return; }else if(sz==n-1){ Bottom(t); return; } spt.Del_root(); spt.Insert(t,sz); } void Solve(int m){ char str[10]; int val,num; while(m--){ scanf("%s",str); if(str[0]=='Q'){//query scanf("%d",&val); printf("%d\n",Query(val)); }else if(str[0]=='T'){//top scanf("%d",&val); Top(spt.Map[val]); }else if(str[0]=='A'){//ask scanf("%d",&val); printf("%d\n",Ask(spt.Map[val])); }else if(str[0]=='B'){//bottom scanf("%d",&val); Bottom(spt.Map[val]); }else if(str[0]=='I'){//insert scanf("%d %d",&val,&num); if(num!=0) Insert(spt.Map[val],num); } } } int main(){ int m; scanf("%d %d",&n,&m); Init(n); Solve(m); return 0; }
相关文章推荐
- BZOJ1861: [Zjoi2006]Book 书架 Splay
- 【BZOJ1861】【Zjoi2006】Book 书架 Splay
- BZOJ 1861: [Zjoi2006]Book 书架 | SPlay 板题
- BZOJ-1861 Book 书架 Splay
- [BZOJ1861][Zjoi2006]Book 书架 && splay
- BZOJ-1861 Book 书架 Splay
- bzoj1861: [Zjoi2006]Book 书架 平衡树 Splay
- 【BZOJ 1861】[Zjoi2006]Book 书架 splay
- BZOJ 1861 ZJOI2006 Book 书架 Splay
- BZOJ_1861_[Zjoi2006]Book 书架_splay
- bzoj1861 book书架 splay
- BZOJ 1861 Book 书架(splay)
- splay学习小结1.1【BZOJ 1861】[Zjoi2006]Book 书架
- 【BZOJ1861】【splay】Book 书架
- BZOJ 1861: [Zjoi2006]Book 书架 (splay)
- BZOJ 1861 ZJOI2006 Book 书架 Splay
- BZOJ 1861 [Zjoi2006]Book 书架 ——Splay
- 【bzoj1861】[Zjoi2006]Book 书架 splay
- BZOJ 1861 ZJOI 2006 Book 书架 Splay
- BZOJ 1861: [Zjoi2006]Book 书架 splay