首页 > 代码库 > [Zjoi2006]Book 书架

[Zjoi2006]Book 书架

<style>pre.cjk { font-family: "Droid Sans Fallback", monospace } p { margin-bottom: 0.25cm; line-height: 120% } a:link { }</style>

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 }

 

 

[Zjoi2006]Book 书架