BZOJ1861: [Zjoi2006]Book 书架
Posted 符拉迪沃斯托克
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了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
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
9
9
7
5
3
HINT
数据范围
2. Insert操作就是把要操作的节点和前驱后继交换位置,即:把两个点的特征值即编号进行交换。
3. Ask操作询问序列中在此节点前面的数有多少个,提到根节点输出左儿子size就可以了。
4. Query操作就是一个简单的查询序列中第s个数的编号,相当于查询第k大,kth即可。
由于我们需要定位编号为s的节点在树中的位置,所以我使用了 id 数组记录并维护。
附代码:
#include<iostream> #include<algorithm> #include<cstdio> #define MAXN 80010 using namespace std; int n,m,root=1,c=1,id[MAXN]; struct node{ int son[2]; int f,v,s; }a[MAXN]; inline int read(){ int date=0,w=1;char c=0; while(c<‘0‘||c>‘9‘){if(c==‘-‘)w=-1;c=getchar();} while(c>=‘0‘&&c<=‘9‘){date=date*10+c-‘0‘;c=getchar();} return date*w; } inline void clean(int rt){ a[rt].son[0]=a[rt].son[1]=a[rt].f=a[rt].v=a[rt].s=0; } inline void pushup(int rt){ if(!rt)return; a[rt].s=a[a[rt].son[0]].s+a[a[rt].son[1]].s+1; id[a[a[rt].son[0]].v]=a[rt].son[0];id[a[a[rt].son[1]].v]=a[rt].son[1]; } inline void turn(int rt,int k){ int x=a[rt].f,y=a[x].f; a[x].son[k^1]=a[rt].son[k]; if(a[rt].son[k])a[a[rt].son[k]].f=x; a[rt].f=y; if(y)a[y].son[a[y].son[1]==x]=rt; a[x].f=rt; a[rt].son[k]=x; pushup(x);pushup(rt); } void splay(int rt,int ancestry){ while(a[rt].f!=ancestry){ int x=a[rt].f,y=a[x].f; if(y==ancestry)turn(rt,a[x].son[0]==rt); else{ int k=a[y].son[0]==x?1:0; if(a[x].son[k]==rt){turn(rt,k^1);turn(rt,k);} else{turn(x,k);turn(rt,k);} } } if(ancestry==0)root=rt; } int kth(int rt,int x){ int y=a[rt].son[0]; if(a[y].s+1==x)return rt; else if(x<=a[y].s)return kth(y,x); else return kth(a[rt].son[1],x-a[y].s-1); } inline void newnode(int x){ int rt=c++; a[rt].son[0]=a[rt].son[1]=0; a[rt].v=x;a[rt].s=1;id[x]=rt; if(rt==1)return; a[rt-1].son[1]=rt;a[rt].f=rt-1; splay(rt,0); } inline void top(int x){ int rt=id[x]; splay(rt,0); if(!a[rt].son[0])return; if(!a[rt].son[1]){ a[rt].son[1]=a[rt].son[0]; a[rt].son[0]=0; } else{ int y=kth(root,a[a[rt].son[0]].s+2); a[a[root].son[0]].f=y; a[y].son[0]=a[root].son[0]; a[root].son[0]=0; splay(y,0); } } inline void bottom(int x){ int rt=id[x]; splay(rt,0); if(!a[rt].son[1])return; if(!a[rt].son[0]){ a[rt].son[0]=a[rt].son[1]; a[rt].son[1]=0; } else{ int y=kth(root,a[a[rt].son[0]].s); a[a[root].son[1]].f=y; a[y].son[1]=a[root].son[1]; a[root].son[1]=0; splay(y,0); } } inline void insert(int x,int y){ if(!y)return; splay(id[x],0); int p,q,k=kth(root,a[a[id[x]].son[0]].s+y+1); p=a[k].v;q=id[x]; swap(id[x],id[p]);swap(a[q].v,a[k].v); } inline int ask(int x){ x=id[x]; splay(x,0); return a[a[x].son[0]].s; } int main(){ char ch[10]; int x,y; n=read();m=read(); for(int i=1;i<=n;i++){ x=read(); newnode(x); } while(m--){ scanf("%s",ch);x=read(); switch(ch[0]){ case ‘T‘:top(x);break; case ‘B‘:bottom(x);break; case ‘I‘:y=read();insert(x,y);break; case ‘A‘:printf("%d\n",ask(x));break; case ‘Q‘:printf("%d\n",a[kth(root,x)].v);break; } } return 0; }
以上是关于BZOJ1861: [Zjoi2006]Book 书架的主要内容,如果未能解决你的问题,请参考以下文章
[bzoj1861][Zjoi2006]Book 书架_非旋转Treap