[BZOJ1861][Zjoi2006]Book 书架

试题描述

小T有一个很大的书柜。这个书柜的构造有些独特,即书柜里的书是从上至下堆放成一列。她用1到n的正整数给每本书都编了号。 小T在看书的时候,每次取出一本书,看完后放回书柜然后再拿下一本。由于这些书太有吸引力了,所以她看完后常常会忘记原来是放在书柜的什么位置。不过小T的记忆力是非常好的,所以每次放书的时候至少能够将那本书放在拿出来时的位置附近,比如说她拿的时候这本书上面有X本书,那么放回去时这本书上面就只可能有X-1、X或X+1本书。 当然也有特殊情况,比如在看书的时候突然电话响了或者有朋友来访。这时候粗心的小T会随手把书放在书柜里所有书的最上面或者最下面,然后转身离开。 久而久之,小T的书柜里的书的顺序就会越来越乱,找到特定的编号的书就变得越来越困难。于是她想请你帮她编写一个图书管理程序,处理她看书时的一些操作,以及回答她的两个提问:(1)编号为X的书在书柜的什么位置;(2)从上到下第i本书的编号是多少。

输入

第一行有两个数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本书的编号。

输出

对于每一条Ask或Query语句你应该输出一行,一个数,代表询问的答案。

输入示例

  1.  
  2. Query
  3. Top
  4. Ask
  5. Bottom
  6. Ask
  7. Top
  8. Insert -
  9. Query
  10. Query
  11. Ask

输出示例

  1.  

数据规模及约定

100%的数据,n,m < = 80000

题解

让每个节点的编号与它在伸展树中的编号一致,查找排名时利用子树大小,查询某节点排名时把它伸展到根就好了。

  1. #include <iostream>
  2. #include <cstdio>
  3. #include <cstdlib>
  4. #include <cstring>
  5. #include <cctype>
  6. #include <algorithm>
  7. using namespace std;
  8.  
  9. int read() {
  10. int x = 0, f = 1; char c = getchar();
  11. while(!isdigit(c)){ if(c == '-') f = -1; c = getchar(); }
  12. while(isdigit(c)){ x = x * 10 + c - '0'; c = getchar(); }
  13. return x * f;
  14. }
  15.  
  16. #define maxn 80010
  17. struct Node {
  18. int siz;
  19. Node() {}
  20. } ns[maxn];
  21. int ToT, fa[maxn], ch[2][maxn], id[maxn];
  22. void maintain(int o) {
  23. ns[o].siz = 1;
  24. for(int i = 0; i < 2; i++) if(ch[i][o])
  25. ns[o].siz += ns[ch[i][o]].siz;
  26. return ;
  27. }
  28. void build(int& o, int l, int r) {
  29. if(l > r) return ;
  30. int mid = l + r >> 1; o = id[mid];
  31. build(ch[0][o], l, mid - 1); build(ch[1][o], mid + 1, r);
  32. if(ch[0][o]) fa[ch[0][o]] = o;
  33. if(ch[1][o]) fa[ch[1][o]] = o;
  34. return maintain(o);
  35. }
  36. void rotate(int u) {
  37. int y = fa[u], z = fa[y], l = 0, r = 1;
  38. if(z) ch[ch[1][z]==y][z] = u;
  39. if(ch[1][y] == u) swap(l, r);
  40. fa[u] = z; fa[y] = u; fa[ch[r][u]] = y;
  41. ch[l][y] = ch[r][u]; ch[r][u] = y;
  42. maintain(y); maintain(u);
  43. return ;
  44. }
  45. void splay(int u) {
  46. while(fa[u]) {
  47. int y = fa[u], z = fa[y];
  48. if(z) {
  49. if(ch[0][y] == u ^ ch[0][z] == y) rotate(u);
  50. else rotate(y);
  51. }
  52. rotate(u);
  53. }
  54. return ;
  55. }
  56. int splitl(int u) {
  57. splay(u);
  58. int tmp = ch[0][u];
  59. fa[tmp] = ch[0][u] = 0;
  60. maintain(u);
  61. return tmp;
  62. }
  63. int splitr(int u) {
  64. splay(u);
  65. int tmp = ch[1][u];
  66. fa[tmp] = ch[1][u] = 0;
  67. maintain(u);
  68. return tmp;
  69. }
  70. int merge(int a, int b) {
  71. if(!a) return maintain(b), b;
  72. if(!b) return maintain(a), a;
  73. while(ch[1][a]) a = ch[1][a];
  74. splay(a);
  75. ch[1][a] = b; fa[b] = a;
  76. return maintain(a), a;
  77. }
  78. int getrt() {
  79. int u = 1; while(fa[u]) u = fa[u];
  80. return u;
  81. }
  82. int Find(int o, int k) {
  83. if(!o) return 0;
  84. int ls = ch[0][o] ? ns[ch[0][o]].siz : 0;
  85. if(k == ls + 1) return o;
  86. if(k > ls + 1) return Find(ch[1][o], k - ls - 1);
  87. return Find(ch[0][o], k);
  88. }
  89.  
  90. int main() {
  91. int n = read(), q = read();
  92. for(int i = 1; i <= n; i++) id[i] = read();
  93. int tmp = 0; build(tmp, 1, n);
  94.  
  95. int tq = q;
  96. while(q--) {
  97. char cmd[10]; scanf("%s", cmd);
  98. if(cmd[0] == 'T') {
  99. int mrt = read(), lrt = splitl(mrt), rrt = splitr(mrt);
  100. lrt = merge(lrt, rrt); merge(mrt, lrt);
  101. }
  102. if(cmd[0] == 'B') {
  103. int mrt = read(), lrt = splitl(mrt), rrt = splitr(mrt);
  104. lrt = merge(lrt, rrt); merge(lrt, mrt);
  105. }
  106. if(cmd[0] == 'I') {
  107. int mrt = read(), t = read(), rk, lrt, rrt;
  108. if(!t) continue;
  109. splay(mrt); rk = (ch[0][mrt] ? ns[ch[0][mrt]].siz : 0) + 1 + t;
  110. if(rk < 1 || rk > n) continue; rk = Find(getrt(), rk);
  111. if(t < 0) {
  112. lrt = splitl(rk); splitl(mrt); rrt = splitr(mrt);
  113. lrt = merge(lrt, mrt); lrt = merge(lrt, rk); merge(lrt, rrt);
  114. }
  115. else {
  116. lrt = splitl(mrt); splitl(rk); rrt = splitr(rk);
  117. lrt = merge(lrt, rk); lrt = merge(lrt, mrt); merge(lrt, rrt);
  118. }
  119. }
  120. if(cmd[0] == 'A') {
  121. int u = read();
  122. splay(u);
  123. printf("%d\n", ch[0][u] ? ns[ch[0][u]].siz : 0);
  124. }
  125. if(cmd[0] == 'Q') printf("%d\n", Find(getrt(), read()));
  126. }
  127.  
  128. return 0;
  129. }

[BZOJ1861][Zjoi2006]Book 书架的更多相关文章

  1. [bzoj1861][Zjoi2006]Book 书架_非旋转Treap

    Book 书架 bzoj-1861 Zjoi-2006 题目大意:给你一个序列,支持:将指定编号的元素抽出,放到序列顶(底):将指定编号元素左右篡位:查询指定编号元素位置:查询指定数量位置元素编号. ...

  2. fhq_treap || BZOJ1861: [Zjoi2006]Book 书架 || Luogu P2596 [ZJOI2006]书架

    题面:P2596 [ZJOI2006]书架 题解:记录每本书对应的节点编号 普通fhq_treap无法查询一个权值的排名,所以在普通fhq_treap上多记录每个节点的父亲(可加在pushup函数中) ...

  3. BZOJ1861[ZJOI2006]Book书架

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

  4. 【平衡树】【pb_ds】 bzoj1861 [Zjoi2006]Book 书架

    需要用数组记录编号为i的书的位置,和位置i处的书的编号. Code: #include<cstdio> #include<ext/pb_ds/assoc_container.hpp& ...

  5. 【权值分块】bzoj1861 [Zjoi2006]Book 书架

    权值分块……rank3……没什么好说的. #include<cstdio> #include<cmath> #include<algorithm> using na ...

  6. bzoj1861 [Zjoi2006]Book 书架 splay

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

  7. 并不对劲的bzoj1861: [Zjoi2006]Book 书架

    传送门-> 这题的正确做法是splay维护这摞书. 但是并不对劲的人选择了暴力(皮这一下很开心). #include<algorithm> #include<cmath> ...

  8. bzoj1861 [Zjoi2006]Book 书架——splay

    题目:https://www.lydsy.com/JudgeOnline/problem.php?id=1861 发现自己想splay的时候总是纠结那个点权是什么,因为splay原本是二分查找树... ...

  9. BZOJ 1861: [Zjoi2006]Book 书架

    1861: [Zjoi2006]Book 书架 Time Limit: 4 Sec  Memory Limit: 64 MBSubmit: 1290  Solved: 740[Submit][Stat ...

随机推荐

  1. C Primer Plus 学习体会

    本月刚刚开始学习<C primer plus>,之前课上草草学过一遍,讲到指针就结束了.现在重新开始看感觉难度不大只是刚开始接触有些语言细节比较琐碎.学习这一周的体会如下: 诸多前辈推荐的 ...

  2. ping环回地址和ping主机地址的区别

    ping127.0.0.1和ping本机的过程是不一样的ip输出函数先检查地址是不是环回地址1.如果是环回地址 直接交给环回驱动程序处理 返回ip输入函数2.如果不是环回地址 检查是不是广播或者多播地 ...

  3. minHash最小哈希原理

    minHash最小哈希原理 收藏 初雪之音 发表于 9个月前 阅读 208 收藏 9 点赞 1 评论 0 摘要: 在数据挖掘中,一个最基本的问题就是比较两个集合的相似度.通常通过遍历这两个集合中的所有 ...

  4. c#线程带参数

    c#线程带参数 ThreadStart threadStart = delegate { LoadPicture(ds.Tables[0]); }; Thread thread = new Threa ...

  5. 理解OAuth 2.0

    转自:http://www.ruanyifeng.com/blog/2014/05/oauth_2_0.html OAuth是一个关于授权(authorization)的开放网络标准,在全世界得到广泛 ...

  6. CURL HELP

    CURL下载 在windows的系统环境变量中,将CURL的路径(curl.exe存放的路径)复制到"Path"变量的结尾 Usage: curl [options...] < ...

  7. 菜鸟git学习

    基础知识: 安装github之后,所有的命令在git shell 中输入. E:\文档\GitHub [master +2 ~0 -0 !]> cd [ToDoList]E:\文档\GitHub ...

  8. dateRangePicker时间范围控件

    Github:https://github.com/dangrossman/bootstrap-daterangepicker/ 使用daterangepicker()为元素创建一个时间范围控件 &l ...

  9. Bzoj1305 [CQOI2009]dance跳舞

    Time Limit: 5 Sec  Memory Limit: 162 MBSubmit: 2925  Solved: 1221 Description 一次舞会有n个男孩和n个女孩.每首曲子开始时 ...

  10. Nginx配置SSL证书部署HTTPS网站

    1.购买ssl证书 购买网站:沃通 2.上传证书到nginx服务器,然后进行解压. 解压后的的效果: [root@bubidev-ng3 nginx]# pwd/etc/nginx [root@bub ...