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

Sample Output

2
9
9
7
5
3

HINT

 

数据范围


100%的数据,n,m < = 80000
 
题解:
基本上是splay模板题吧……
操作都很容易实现,就是需要记录一下编号为x的书在splay的什么位置
这块我想了好久才想明白,不管这个点位置怎么变它在splay中始终是这个点,所以只在插入点时记录一下就好了(pos数组)
比最普通的模板多了一个Get_Rank,用来求这个点是splay中的第几个点:先加上这个点左子的size,然后不断往上走,若是parent的右子则需要加上parent左子的size+1
 
代码:
  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 }
View Code

 

posted @ 2017-06-08 15:58  秋千旁的蜂蝶~  阅读(178)  评论(0编辑  收藏  举报