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

Solution

显然可以用fhqtreap按位置分裂来解决所有的操作。
但是要注意一个问题,fhqtreap按位置分裂那么序号就乱序了,不能在树上往下爬来找数的排名。
考虑对每个节点维护一个父指针,在插入的时候把数的位置记录下来(即这个数在treap中的编号)。
那么查询的时候,从当前节点往上爬,如果它是右儿子的话,证明左儿子及父亲都是它前面的数,一直爬到根就可以知道它是第几大了。然后就是正常的fhqtreap按位置分裂操作了(注意操作时是对这个数的pos操作,即对这个数在treap中的编号操作)。

#include <bits/stdc++.h>
using namespace std;
#define N 100010
#define lc (t[rt].l)
#define rc (t[rt].r)
int n, m, root, tot, pos[N];
struct fhq { int l, r, siz, rnd, val, fa; } t[N];
void up(int rt) { t[rt].siz = 1 + t[lc].siz + t[rc].siz; t[lc].fa = t[rc].fa = rt;
}
void split(int rt, int &l, int &r, int k) {if(!k) l = 0, r = rt;else if(k == t[rt].siz) l = rt, r = 0;else if(k <= t[lc].siz) r = rt, split(lc, l, lc, k), up(rt);else l = rt, split(rc, rc, r, k - t[lc].siz - 1), up(rt);
}
void merge(int &rt, int l, int r) {if(!l || !r) rt = l + r;else if(t[l].rnd < t[r].rnd) rt = l, merge(rc, rc, r), up(rt);else rt = r, merge(lc, l, lc), up(rt);
}
int build(int v) {t[++tot] = (fhq) {0, 0, 1, rand()<<15|rand(), v, 0}; return tot;
}
int find(int rt) {int rk = t[lc].siz + 1;while(t[rt].fa) {if(t[t[rt].fa].r == rt) rk += t[t[t[rt].fa].l].siz + 1;rt = t[rt].fa;}return rk;
}
void top(int s) {int x, y, tmp, rk = find(s);split(root, x, y, rk); split(x, x, tmp, rk - 1);merge(x, tmp, x); merge(root, x, y);
}
void down(int s) {int x, y, tmp, rk = find(s);split(root, x, y, rk); split(x, x, tmp, rk - 1);merge(root, x, y); merge(root, root, tmp);
}
void ins(int s, int t) {if(!t) return;int x, y, z, tmp, rk = find(s);split(root, x, y, rk); split(x, x, tmp, rk - 1);if(t == -1) {split(x, x, z, rk - 2); merge(x, x, tmp); merge(x, x, z);merge(root, x, y);} else {split(y, z, y, 1);merge(x, x, z); merge(x, x, tmp); merge(root, x, y);}
}
int ask(int s) {int x, y, ans, rk = find(s);split(root, x, y, rk - 1);ans = t[x].siz;merge(root, x, y);return ans;
}
int query(int s) {int x, y, ans, tmp;split(root, x, y, s); split(x, x, tmp, s - 1);ans = t[tmp].val;merge(x, x, tmp); merge(root, x, y);return ans;
}
int main() {scanf("%d%d", &n, &m); char ch[10];for(int i = 1, x; i <= n; ++i) {scanf("%d", &x); pos[x] = i;merge(root, root, build(x));}for(int s, t, i = 1; i <= m; ++i) {scanf("%s%d", ch, &s);if(ch[0] == 'T') top(pos[s]);else if(ch[0] == 'B') down(pos[s]);else if(ch[0] == 'I') scanf("%d", &t), ins(pos[s], t);else if(ch[0] == 'A') printf("%d\n", ask(pos[s]));else printf("%d\n", query(s));}
}

转载于:https://www.cnblogs.com/henry-1202/p/10505119.html

BZOJ1861: [Zjoi2006]Book 书架相关推荐

  1. bzoj1861[Zjoi2006]Book 书架

    bzoj1861[Zjoi2006]Book 书架 题意: 维护一个序列,支持移动元素,查询元素是第几个,查询第k个元素编号. 题解: 可以用treap和splay,我写的是splay.移动元素就是先 ...

  2. splay伸展树基础操作(bzoj 1861: [Zjoi2006]Book 书架)

    splay:一种排序树(中序遍历权值有序) 主要性质:随着访问翻转次数的增多,复杂度越来越接近logn,形态也越来越接近平衡树 主要功能:每次将要询问or删除or修改的点先一路翻转到根,然后再满足所需 ...

  3. BZOJ1861:[ZJOI2006]书架(Splay)

    Description 小T有一个很大的书柜.这个书柜的构造有些独特,即书柜里的书是从上至下堆放成一列.她用1到n的正整数给每本书都编了号. 小T在看书的时候,每次取出一本书,看完后放回书柜然后再拿下 ...

  4. 【Splay】【ZJOI2006】书架

    [题目描述] 小T有一个很大的书柜.这个书柜的构造有些独特,即书柜里的书是从上至下堆放成一列.她用1到n的正整数给每本书都编了号.  小T在看书的时候,每次取出一本书,看完后放回书柜然后再拿下一本.由 ...

  5. BZOJ 1861 ZJOI2006 Book 书架 Splay

    题目大意:--自己看懒得打了 很裸的Splay 首先开一个指针数组记录每个值代表的节点 然后就能找到某本书在序列中的什么位置了 总感觉这题可以不用Splay的说--一定是我的错觉 样例中居然尼玛有中文 ...

  6. [Splay伸展树]splay树入门级教程

    首先声明,本教程的对象是完全没有接触过splay的OIer,大牛请右上角.. 首先引入一下splay的概念,他的中文名是伸展树,意思差不多就是可以随意翻转的二叉树 PS:百度百科中伸展树读作:BoGa ...

  7. oracle表空间追加数据文件,oracle数据库表空间追加数据库文件方法

    mysql优化(初学) 写的时候遇到了SQL语句的优化问题,在网上搜了一些学习.http://blog.csdn.net/kennyrose/article/details/7532032 索引: 1 ...

  8. BZOJ ac100题存档

    不知不觉AC100题了,放眼望去好像都是水题.在这里就做一个存档吧(特别感谢各位大神尤其是云神http://hi.baidu.com/greencloud和丽洁姐http://wjmzbmr.com/ ...

  9. luogu P2596 [ZJOI2006]书架(平衡树、无旋treap(按排名分裂)一些更复杂的操作)

    P2596 [ZJOI2006]书架 无旋treap可以维护一棵树的中序遍历结果.但是不支持通过编号来找节点.于是在无旋treap的基础上,我维护了每个节点的父亲,这样就可以求出一个节点是中序遍历中的 ...

最新文章

  1. targetSdkVersion
  2. angular reactive form
  3. Beaglebone Black教程Beaglebone Black中的Cloud9 IDE基本使用
  4. opengl基础学习专题 (二) 点直线和多边形
  5. 【Android 高性能音频】Oboe 音频流打开后 耳机 / 音箱 插拔事件处理 ( 动态注册广播接收者监听耳机插拔事件 | 重新打开 Oboe 音频流 )
  6. 使用Trello看板管理项目
  7. 清华大学计算机系保送,2018年北大、清华五大学科竞赛集训队保送生争夺战结果...
  8. 更改软件typera的编辑页面背景色
  9. 8051中断系统介绍
  10. 【C语言】输出半径1到10的圆的面积,当面积值超过100时,停止执行本程序
  11. java 三个点_Java Object定义三个点如何实现 Java Object定义三个点实现代码
  12. java创建环境变量是用户还是系统_5.Java环境变量配置
  13. Linux下实现一个论文翻译阅读的小工具
  14. mac 未能启动java jar_在Mac上运行.jar
  15. 图片节点html,Qunee for HTML5 - 中文 : 节点图片
  16. 三年上一大台阶,联想凌拓做对了什么?
  17. 小米手机只能显示e或者无服务器,手机出现E网怎么回事
  18. SEO快排是什么?怎样实现快排?
  19. 1分钟推荐一个深度学习领域的必备网站,高能!
  20. android-x86编译

热门文章

  1. java pdf版本转换_Java 转换 PDF 版本
  2. 计算机基本知识实训报告,计算机实训报告小结
  3. p20怎么用android auto,奔驰23P/P20驾驶辅助系统到底有哪些功能,怎么使用?
  4. 复练-软考网规-两地三中心
  5. c mysql异常捕获异常,c#基础之异常处理及自定义异常 从SQLServer转储数据到MySQL...
  6. 1900-01-01t00:00:00+08:00 java_日期格式转换 java 2016-09-03T00:00:00.000+08:00
  7. 前端技术的概括以及html的基本知识总结
  8. 想精通正则表达式 这几个正则表达式学习资料及工具你必须有!
  9. Flow 常用知识点整理
  10. 2018前端学习总结