pre.cjk { font-family: "Droid Sans Fallback", monospace }
p { margin-bottom: 0.25cm; line-height: 120% }
a:link { }
1861: [Zjoi2006]Book 书架
Time Limit: 4 Sec Memory Limit: 64 MB
Submit: 1581 Solved: 884
[Submit][Status][Discuss]
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本书的编号。
Output
对于每一条Ask或Query语句你应该输出一行,一个数,代表询问的答案。
Sample Input
10 10
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
Sample Output
2
9
9
7
5
3
HINT
数据范围
100%的数据,n,m < = 80000
id[i]记录编号为i的书在SPLAY中的结点编号,key[i]记录splay中的i结点的书的编号。
splay维护书架上从上到下的书。
TOP:把这本书找到,删掉。然后把最前面的那本书旋转到根,然后把这本书放在根的右儿子。
Bottom类似。
Insert:把这本书找到删掉,然后在相应的位置插入即可。
Ask:旋转到根,查询左儿子的size即可。
Query:用size查找即可。
还有数组要开两倍以上,因为有很多新加结点的操作。
感觉很复杂,调废我。
1 #include <algorithm> 2 #include <iostream> 3 #include <cstdlib> 4 #include <cstring> 5 #include <cstdio> 6 #include <cmath> 7 #define maxn 200010 8 using namespace std; 9 int ch[maxn][2],pre[maxn],size[maxn],key[maxn],id[maxn],tot=0,root=1; 10 char s[10]; 11 inline void Rotate(int x,int kind){ 12 int y=pre[x]; 13 ch[y][!kind]=ch[x][kind]; 14 pre[ch[x][kind]]=y; 15 if(pre[y]) 16 ch[pre[y]][ch[pre[y]][1]==y]=x; 17 pre[x]=pre[y]; 18 ch[x][kind]=y; 19 pre[y]=x; 20 size[y]=size[ch[y][0]]+size[ch[y][1]]+1; 21 size[x]=size[ch[x][0]]+size[ch[x][1]]+1; 22 } 23 inline void splay(int r,int goal){ 24 while(pre[r]!=goal){ 25 if(pre[pre[r]]==goal) 26 Rotate(r,ch[pre[r]][0]==r); 27 else{ 28 int y=pre[r]; 29 int kind=ch[pre[y]][0]==y; 30 if(ch[y][kind]==r){ 31 Rotate(r,!kind); 32 Rotate(r,kind); 33 } 34 else{ 35 Rotate(y,kind); 36 Rotate(r,kind); 37 } 38 } 39 } 40 if(goal==0) root=r; 41 } 42 void newnode(int &x,int fa,int keyy){ 43 x=++tot; 44 pre[x]=fa; 45 size[x]=1; 46 key[x]=keyy; 47 } 48 void query(int x){ 49 int rt=root; 50 while(x){ 51 if(size[ch[rt][0]]+1==x) break; 52 if(size[ch[rt][0]]+1<x) x-=(size[ch[rt][0]]+1),rt=ch[rt][1]; 53 else rt=ch[rt][0]; 54 } 55 printf("%d\n",key[rt]); 56 } 57 void top(int x){ 58 int kt=id[x]; 59 splay(kt,0); 60 if(!ch[kt][0]) return; 61 int p1=ch[kt][0]; 62 while(ch[p1][1]) p1=ch[p1][1]; 63 splay(p1,root); 64 if(!ch[kt][1]) root=ch[kt][0],pre[ch[kt][0]]=0; 65 else{ 66 int p2=ch[kt][1]; 67 while(ch[p2][0]) p2=ch[p2][0]; 68 splay(p2,root); 69 pre[p1]=0; 70 pre[p2]=p1; 71 ch[p1][1]=p2; 72 root=p1; 73 } 74 int rt=p1; 75 while(ch[rt][0]) rt=ch[rt][0]; 76 splay(rt,0); 77 newnode(ch[root][0],root,x); 78 size[root]=size[ch[root][0]]+size[ch[root][1]]+1; 79 id[x]=ch[root][0]; 80 } 81 void bottom(int x){ 82 int kt=id[x]; 83 splay(kt,0); 84 if(!ch[kt][1]) return; 85 int p1=ch[kt][1]; 86 while(ch[p1][0]) 87 p1=ch[p1][0]; 88 splay(p1,root); 89 if(!ch[kt][0]) root=ch[kt][1],pre[ch[kt][1]]=0; 90 else{ 91 int p2=ch[kt][0]; 92 while(ch[p2][1]) p2=ch[p2][1]; 93 splay(p2,root); 94 pre[p1]=0; 95 pre[p2]=p1; 96 ch[p1][0]=p2; 97 root=p1; 98 } 99 int rt=p1; 100 while(ch[rt][1]) rt=ch[rt][1]; 101 splay(rt,0); 102 newnode(ch[root][1],root,x); 103 size[root]=size[ch[root][0]]+size[ch[root][1]]+1; 104 id[x]=ch[root][1]; 105 } 106 void Insert(int x){ 107 int k; 108 scanf("%d",&k); 109 if(k==0) return; 110 splay(id[x],0); 111 if(k==1){ 112 int rt=ch[root][1]; 113 if(rt==0) return; 114 while(ch[rt][0]) rt=ch[rt][0]; 115 splay(rt,root); 116 pre[ch[root][1]]=0; 117 pre[ch[root][0]]=ch[root][1]; 118 ch[ch[root][1]][0]=ch[root][0]; 119 root=ch[root][1]; 120 rt=ch[root][1]; 121 size[root]++; 122 if(rt==0) newnode(ch[root][1],root,x),id[x]=ch[root][1]; 123 else{ 124 while(ch[rt][0]) size[rt]++,rt=ch[rt][0]; 125 size[rt]++; 126 newnode(ch[rt][0],rt,x); 127 id[x]=ch[rt][0]; 128 } 129 } 130 else{ 131 int rt=ch[root][0]; 132 if(rt==0) return; 133 while(ch[rt][1]) rt=ch[rt][1]; 134 splay(rt,root); 135 pre[ch[root][0]]=0; 136 pre[ch[root][1]]=ch[root][0]; 137 ch[ch[root][0]][1]=ch[root][1]; 138 root=ch[root][0]; 139 rt=ch[root][0]; 140 size[root]++; 141 if(rt==0) newnode(ch[root][0],root,x),id[x]=ch[root][0]; 142 else{ 143 while(ch[rt][1]) size[rt]++,rt=ch[rt][1]; 144 size[rt]++; 145 newnode(ch[rt][1],rt,x); 146 id[x]=ch[rt][1]; 147 } 148 } 149 } 150 void ask(int x){ 151 int k=id[x]; 152 splay(k,0); 153 printf("%d\n",size[ch[k][0]]); 154 } 155 int main() 156 { 157 int n,m,x; 158 scanf("%d%d",&n,&m); 159 scanf("%d",&x); 160 id[x]=1;pre[1]=0; 161 key[1]=x; 162 size[1]=n; 163 for(int i=2;i<=n;i++){ 164 scanf("%d",&x); 165 ch[i-1][1]=i; 166 pre[i]=i-1; 167 size[i]=n-i+1; 168 id[x]=i; 169 key[i]=x; 170 } 171 if(n>2) 172 splay(n/2,0); 173 tot=n; 174 for(int i=1;i<=m;i++){ 175 scanf("%s%d",s,&x); 176 if(s[0]==‘Q‘) query(x); 177 if(s[0]==‘T‘) top(x); 178 if(s[0]==‘B‘) bottom(x); 179 if(s[0]==‘I‘) Insert(x); 180 if(s[0]==‘A‘) ask(x); 181 } 182 return 0; 183 }