bzoj 1861: [Zjoi2006]Book 书架
2016-04-07 17:33
302 查看
1861: [Zjoi2006]Book 书架
Time Limit: 4 Sec Memory Limit: 64 MBSubmit: 1133 Solved: 657
[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 101 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
29
9
7
5
3
HINT
数据范围100%的数据,n,m < = 80000
Source
Day2#include<iostream> #include<cstdio> #include<cstring> #include<algorithm> #define N 1600000 using namespace std; int n,m; int a ,key ,size ,ch [3],fa ,sz,root,pd ; int head=0,tail=0; void clear(int x) { size[x]=ch[x][1]=ch[x][0]=fa[x]=key[x]; } int get(int x) { return ch[fa[x]][1]==x; } void update(int x) { size[x]=size[ch[x][0]]+size[ch[x][1]]+1; } void rotate(int x) { int y=fa[x]; int z=fa[y]; int which=get(x); ch[y][which]=ch[x][which^1]; fa[ch[y][which]]=y; ch[x][which^1]=y; fa[y]=x; fa[x]=z; if (z) ch[z][ch[z][1]==y]=x; update(y); update(x); } void splay(int x) { for (int f;(f=fa[x]);rotate(x)) if (fa[f]) rotate(get(x)==get(f)?f:x); root=x; } int build(int l,int r) { if (r<l) return 0; if (l==r) { key[++sz]=a[l]; size[sz]=1; ch[sz][1]=ch[sz][0]=0; pd[a[l]]=sz; if (l==1) head=sz; if (l==n) tail=sz; return sz; } int mid=(l+r)/2; int now=++sz; ch[now][0]=build(l,mid-1); ch[now][1]=build(mid+1,r); fa[ch[now][0]]=fa[ch[now][1]]=now; size[now]=size[ch[now][0]]+size[ch[now][1]]+1; if (mid==1) head=now; if (mid==n) tail=now; key[now]=a[mid]; pd[a[mid]]=now; return now; } int findx(int x) { int now=root; while(true) { if (x<=size[ch[now][0]]) now=ch[now][0]; else { int temp=size[ch[now][0]]+1; if (temp==x) return now; x-=temp; now=ch[now][1]; } } } int next() { int now=ch[root][1]; while(ch[now][0]) now=ch[now][0]; return now; } int pre() { int now=ch[root][0]; while(ch[now][1]) now=ch[now][1]; return now; } void del(int x) { int k=pd[x]; splay(k); if (!ch[root][0]&&!ch[root][1]) { clear(root); root=0; return; } if (!ch[root][0]) { int old=root; root=ch[root][1]; fa[root]=0; clear(old); return; } if (!ch[root][1]) { int old=root; root=ch[root][0]; fa[root]=0; clear(old); return; } int f=pre(); int old=root; splay(f); ch[root][1]=ch[old][1]; fa[ch[old][1]]=root; clear(old); update(root); } int main() { scanf("%d%d",&n,&m); for (int i=1;i<=n;i++) { scanf("%d",&a[i]); } sz=0; root=build(1,n); for (int i=1;i<=m;i++) { //cout<<i<<endl; cout<<head<<" "<<pd[3]<<endl; char s[10]; scanf("%s",s); if (s[0]=='A') { int x; scanf("%d",&x); splay(pd[x]); printf("%d\n",size[ch[root][0]]); } if (s[0]=='Q') { int x; scanf("%d",&x); printf("%d\n",key[findx(x)]); } if (s[0]=='T') { int x; scanf("%d",&x); //if (pd[x]==tail) tail=findx(n-1); del(x); int t=findx(1); splay(t); ch[root][0]=++sz; key[sz]=x; pd[x]=sz; size[sz]=1; fa[sz]=root; update(root); head=sz; splay(sz); } if (s[0]=='B') { int x; scanf("%d",&x); if (tail==pd[x]) continue; //if (pd[x]==head) head=findx(2); del(x); int t=findx(n-1); splay(t); ch[root][1]=++sz; key[sz]=x; pd[x]=sz; size[sz]=1; fa[sz]=root; update(root); tail=sz; splay(sz); } if (s[0]=='I') { int x,t; scanf("%d%d",&x,&t); if (t==0) continue; splay(pd[x]); int l=pd[x]; if (t==1) { int k=next(); //if (k==tail) tail=l; int ky=key[k]; key[k]=x; pd[x]=k; key[l]=ky; pd[ky]=l; splay(pd[x]); } else { int k=pre(); //if (head==k) head=l; int ky=key[k]; key[k]=x; pd[x]=k; key[l]=ky; pd[ky]=l; splay(pd[x]); } } } }
相关文章推荐
- java 自定义注解
- lintcode(480)——二叉树的所有路径
- Oracle物化视图
- VB上课心得体会
- zepto.js的事件处理
- D-U-N-S (邓白氏)号申请最新流程的心得
- 软件工程作业05,数组01
- sublime DocBlockre
- 习近平用典 丨 任贤篇:不拘一格降人才
- (8)
- linux下查看某一软件是否安装
- 可变参数变量模板
- mysql 字符串替换 REPLACE()函数 剔除内容中空格换行回车
- Vsync从HWC到APP的传递过程
- 字符串的排列组合
- camera驱动部分视频数据流分析(uvc)
- 如何在C++代码中访问并调用Java的成员呢?
- 10数求和
- 多行输入*号构成菱形
- 循环(4)