bzoj1861:[Zjoi2006]Book 书架
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
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
9
9
7
5
3
HINT
数据范围
100%的数据,n,m < = 80000
题解:
基本上是splay模板题吧……
操作都很容易实现,就是需要记录一下编号为x的书在splay的什么位置
这块我想了好久才想明白,不管这个点位置怎么变它在splay中始终是这个点,所以只在插入点时记录一下就好了(pos数组)
比最普通的模板多了一个Get_Rank,用来求这个点是splay中的第几个点:先加上这个点左子的size,然后不断往上走,若是parent的右子则需要加上parent左子的size+1
代码:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 #include<cstdio> 2 #include<iostream> 3 using namespace std; 4 5 const int MAXN=80005; 6 struct node 7 { 8 int d,size; 9 node *parent,*ch[2]; 10 }pool[MAXN],*root,*rf,*tmp; 11 int cnt,pos[MAXN]; 12 int size(node *p) 13 { 14 if(p) return p->size; 15 return 0; 16 } 17 void update(node *p) 18 { 19 p->size=1+size(p->ch[0])+size(p->ch[1]); 20 } 21 void rotate(node *p,int type) 22 { 23 node *parent=p->parent,*son=p->ch[!type],*gp=p->parent->parent; 24 parent->ch[type]=son; 25 if(son) son->parent=parent; 26 p->ch[!type]=parent; 27 parent->parent=p; 28 p->parent=gp; 29 gp->ch[parent==gp->ch[1]]=p; 30 update(parent); 31 update(p); 32 if(parent==root) root=p; 33 } 34 void splay(node *p,node *target) 35 { 36 while(p->parent!=target) 37 { 38 if(p->parent->parent==target) 39 rotate(p,p==p->parent->ch[1]); 40 else 41 { 42 node *parent=p->parent,*gp=p->parent->parent; 43 int f=parent==gp->ch[0]; 44 if(p==parent->ch[f]) rotate(p,f),rotate(p,!f); 45 else rotate(parent,!f),rotate(p,!f); 46 } 47 } 48 } 49 node *find(node *p,int k) 50 { 51 if(size(p->ch[0])>=k) return find(p->ch[0],k); 52 else if(size(p->ch[0])==k-1) return p; 53 else return find(p->ch[1],k-1-size(p->ch[0])); 54 } 55 void insert(int x,node *newnode) 56 { 57 node *p=find(root,x); 58 splay(p,rf); 59 p=find(root,x+1); 60 splay(p,root); 61 p->ch[0]=newnode; 62 newnode->parent=p; 63 update(p); 64 update(p->parent); 65 } 66 void del(int x) 67 { 68 node *p=find(root,x-1); 69 splay(p,rf); 70 p=find(root,x+1); 71 splay(p,root); 72 p->ch[0]=NULL; 73 update(p); 74 update(p->parent); 75 } 76 int Get_Rank(node *p) 77 { 78 int ret=size(p->ch[0]); 79 while(p!=root) 80 { 81 if(p==p->parent->ch[1]) ret+=1+size(p->parent->ch[0]); 82 p=p->parent; 83 } 84 return ret+1; 85 } 86 87 int main() 88 { 89 int n,m,i,x,y,k,a; 90 char ch[10]; 91 scanf("%d%d",&n,&m); 92 93 rf=&pool[++cnt]; 94 root=&pool[++cnt]; 95 root->d=0;root->size=1; 96 root->parent=rf;rf->ch[0]=root; 97 for(i=1;i<=n;i++) 98 { 99 scanf("%d",&a); 100 pos[a]=++cnt; 101 tmp=&pool[pos[a]]; 102 tmp->d=a;tmp->size=1; 103 tmp->parent=root;root->ch[1]=tmp; 104 splay(tmp,rf); 105 } 106 tmp=&pool[++cnt]; 107 tmp->d=0;tmp->size=1; 108 tmp->parent=root;root->ch[1]=tmp; 109 splay(tmp,rf); 110 111 while(m --> 0) 112 { 113 scanf("%s",ch); 114 if(ch[0]=='T') 115 { 116 scanf("%d",&x); 117 tmp=&pool[pos[x]]; 118 del(Get_Rank(tmp)); 119 insert(1,tmp); 120 } 121 else if(ch[0]=='B') 122 { 123 scanf("%d",&x); 124 tmp=&pool[pos[x]]; 125 del(Get_Rank(tmp)); 126 insert(n,tmp); 127 } 128 else if(ch[0]=='I') 129 { 130 scanf("%d%d",&x,&y); 131 tmp=&pool[pos[x]]; 132 k=Get_Rank(tmp); 133 del(k); 134 insert(k-1+y,tmp); 135 } 136 else if(ch[0]=='A') 137 { 138 scanf("%d",&x); 139 tmp=&pool[pos[x]]; 140 printf("%d\n",Get_Rank(tmp)-2); 141 } 142 else 143 { 144 scanf("%d",&x);x++; 145 printf("%d\n",find(root,x)->d); 146 } 147 } 148 149 return 0; 150 }
既然选择了远方,便只顾风雨兼程