懒得复制,戳我戳我

Solution:

  • 还是一个\(Splay\),我们只用多存一个值\(rad\)来维护二叉树,然后用数组存下每个书对应的值是多少
  • \(Top\)操作,我是把\(s\)旋转到根节点,然后删除,将\(s\)对应的\(rad\)值调至最小,然后插入就可以
  • \(Bottom\)操作,就是和\(Top\)相反,删除后把\(rad\)调整至最大,然后插入
  • \(Insert\)操作,\(s==0\)不用操作,\(-1\)时,就只用把\(s\)旋转到根节点,把左子树最大值旋转至左子树根节点,然后交换两个节点信息,并且交换数组储存的每个书对应的\(rad\),\(1\)就是相反的旋转右子树最小值就可以
  • \(Ask\)操作,就只用把\(s\)旋转到根节点,输出左子树大小
  • \(Query\)操作,就是找第\(s\)大的\(rad\)值对应的书籍编号就可以了
  • 一开始想怎么找编号好久,发现编号是\(1-n\)就好操作了

Code:

  1. //It is coded by Ning_Mew on 4.12
  2. #include<bits/stdc++.h>
  3. #define ls(x) node[x].ch[0]
  4. #define rs(x) node[x].ch[1]
  5. #define fa(x) node[x].fa
  6. #define root node[0].ch[1]
  7. using namespace std;
  8. const int maxn=8e4+10,INF=1e9+7;
  9. int n,m,tot,vall[maxn],low=0,up=0;
  10. struct Node{
  11. int fa,ch[2],val,num,size;//num-> bian hao val->rand()
  12. }node[maxn];
  13. void update(int x){node[x].size=node[ls(x)].size+node[rs(x)].size+1;}
  14. void connect(int x,int fa,int how){node[x].fa=fa;node[fa].ch[how]=x;}
  15. int ident(int x){return x==node[fa(x)].ch[0]?0:1;}
  16. void rorate(int x){
  17. int Y=fa(x),R=fa(Y);int Yson=ident(x),Rson=ident(Y);
  18. connect(node[x].ch[Yson^1],Y,Yson);
  19. connect(Y,x,Yson^1);
  20. connect(x,R,Rson);
  21. update(Y);update(x);
  22. }
  23. void Splay(int x,int goal){
  24. int to=fa(goal);
  25. while(fa(x)!=to){
  26. if(fa(fa(x))==to)rorate(x);
  27. else if(ident(x)==ident(fa(x)))rorate(fa(x)),rorate(x);
  28. else rorate(x),rorate(x);
  29. }
  30. }
  31. int newnode(int x,int rad,int fa){node[++tot].val=rad;node[tot].num=x;node[tot].size=1;node[tot].fa=fa;return tot;}
  32. void ins(int x,int rad){
  33. //cout<<x<<' '<<rad<<endl;
  34. int now=root;
  35. if(!root){newnode(x,rad,0);root=tot;return;}
  36. else{
  37. while(1){
  38. node[now].size++;
  39. int nxt=rad<node[now].val?0:1;
  40. if(!node[now].ch[nxt]){
  41. int p=newnode(x,rad,now);
  42. node[now].ch[nxt]=p;Splay(p,root);return;
  43. }
  44. now=node[now].ch[nxt];
  45. }
  46. }return;
  47. }
  48. int find(int x,int rad){
  49. int now=root;
  50. while(1){
  51. if(!now)return 0;
  52. if(node[now].val==rad){Splay(now,root);return now;}
  53. int nxt=rad<node[now].val?0:1;
  54. now=node[now].ch[nxt];
  55. }
  56. }
  57. void del(int x,int rad,int opt,int sum){//1->del 2->swap
  58. int pos=find(x,rad);
  59. if(!pos)return;
  60. if(opt==1){
  61. if(!ls(pos)&&!rs(pos)){root=0;return;}
  62. if(!ls(pos)){root=rs(pos);fa(root)=0;return;}
  63. else{
  64. int left=ls(pos);
  65. while(rs(left))left=rs(left);
  66. Splay(left,ls(pos));
  67. connect(rs(pos),left,1);
  68. connect(left,0,1);update(left);
  69. }
  70. }else{
  71. if(sum==0)return;
  72. if(sum==-1&&!ls(pos))return;
  73. if(sum==1&&!rs(pos))return;
  74. if(sum==-1){
  75. int left=ls(pos);
  76. while(rs(left))left=rs(left);
  77. Splay(left,ls(pos));
  78. swap(vall[ node[pos].num ],vall[ node[left].num ]);
  79. swap(node[pos].num,node[left].num);
  80. }else{
  81. int right=rs(pos);
  82. while(ls(right))right=ls(right);
  83. Splay(right,rs(pos));
  84. swap(vall[ node[pos].num ],vall[ node[right].num ]);
  85. swap(node[pos].num,node[right].num);
  86. }
  87. }
  88. }
  89. int rak(int x,int rad){int pos=find(x,rad);return node[ls(pos)].size;}
  90. int kth(int x,int rad){
  91. int now=root;
  92. while(1){
  93. if(x-node[ls(now)].size==1){
  94. Splay(now,root);return node[now].num;}
  95. int nxt=x<=node[ls(now)].size?0:1;
  96. if(nxt){x=x-(node[ls(now)].size+1);}
  97. now=node[now].ch[nxt];
  98. }
  99. }
  100. string s;
  101. int main(){
  102. scanf("%d%d",&n,&m);
  103. int x,t;
  104. for(int i=1;i<=n;i++){
  105. scanf("%d",&x);
  106. ins(x,++up);vall[x]=up;
  107. }
  108. //cout<<"ins finished"<<endl;
  109. for(int i=1;i<=m;i++){
  110. cin>>s;scanf("%d",&x);
  111. if(s=="Top"){
  112. del(x,vall[x],1,0);vall[x]=--low;
  113. ins(x,vall[x]);
  114. }
  115. if(s=="Bottom"){
  116. del(x,vall[x],1,0);vall[x]=++up;
  117. ins(x,vall[x]);
  118. }
  119. if(s=="Insert"){
  120. scanf("%d",&t); del(x,vall[x],2,t);
  121. }
  122. if(s=="Ask"){printf("%d\n",rak(x,vall[x]));}
  123. if(s=="Query"){printf("%d\n",kth(x,vall[x]));}
  124. }
  125. return 0;
  126. }

【题解】 [ZJOI2006]书架 (Splay)的更多相关文章

  1. P2596 [ZJOI2006]书架 && Splay 区间操作(三)

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

  2. 洛谷 P2596 [ZJOI2006]书架 (splay)

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

  3. 洛谷.2596.[ZJOI2006]书架(Splay)

    题目链接 /* 五个操作: 1.将某元素置顶.删掉这个数,插入最左 2.将某元素置底.同样 3.旋到根后,直接将这个数与前驱/后继交换所有信息 不是左右子节点! 4.5.裸平衡树 ps:1.用pos[ ...

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

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

  5. [ZJOI2006]书架(权值splay)

    [ZJOI2006]书架(luogu) Description 题目描述 小T有一个很大的书柜.这个书柜的构造有些独特,即书柜里的书是从上至下堆放成一列.她用1到n的正整数给每本书都编了号. 小T在看 ...

  6. 「luogu2569」[ZJOI2006] 书架

    「luogu2569」[ZJOI2006]书架 题目大意 给定一个长度为 \(n\) 序列,序列中第 \(i\) 个元素有编号 \(a_i(a_i \in \Z \cap [1,n])\),需要支持五 ...

  7. 洛谷 P2596 [ZJOI2006]书架 解题报告

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

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

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

  9. [Luogu 2596] ZJOI2006 书架

    [Luogu 2596] ZJOI2006 书架 第一次指针写 FHQ_Treap(省选噩梦数据结构)AC 啦! 省选试机写它,紧张过度失败了. 省选 Day 1 考场写它,写挂了. 省选 Day 1 ...

随机推荐

  1. 将公钥部署到远程Git仓库(coding.net)

    步骤: 1.下载git通用客户端并且安装. 2.右键,在弹出的对话框中选择Git Bash 3.创建本地ssha)在弹出的终端输入ssh-keygen -t rsa -C "username ...

  2. odoo销售转生产

    <!--form view 一个form视图足以--><record id="view_sale_tomrp_form" model="ir.ui.vi ...

  3. [Usaco2005 Open]Disease Manangement 疾病管理 BZOJ1688

    分析: 这个题的状压DP还是比较裸的,考虑将疾病状压,得到DP方程:F[S]为疾病状态为S时的最多奶牛数量,F[S]=max{f[s]+1}; 记得预处理出每个状态下疾病数是多少... 附上代码: # ...

  4. 大数据入门第十五天——HBase整合:云笔记项目

    一.功能简述 1.笔记本管理(增删改) 2.笔记管理 3.共享笔记查询功能 4.回收站 效果预览: 二.库表设计 1.设计理念 将云笔记信息分别存储在redis和hbase中. redis(缓存):存 ...

  5. 【LG3768】简单的数学题

    [LG3768]简单的数学题 题面 求 \[ (\sum_{i=1}^n\sum_{j=1}^nij\text{gcd}(i,j))\text{mod}p \] 其中\(n\leq 10^{10},5 ...

  6. java写个自己的mvc框架学习笔记

    1. 介绍 MVC全名是Model View Controller,是模型(model)-视图(view)-控制器(controller)的缩写,一种软件设计典范,用一种业务逻辑.数据.界面显示分离的 ...

  7. Python RASP 工程化:一次入侵的思考

    前言 今天讲的内容会很深,包括一些 Python的高级用法和一些自己创造的黑科技,前半部分内容你们可能听过,后半部分内容就真的是黑科技了... 深入的研究和思考,总会发现很多有意思的东西.每一次的研究 ...

  8. Microsoft Dynamics CRM 增删改子表汇总子表的某个字段到主表的某个字段(通用插件)

    背景 经常有某个汇总子表的数量到主表的总数量,或者汇总子表的总价到主表的总价这种需求. 传统的做法: 1.就是为每个子表实体单独写成一个插件,但是这样不好复用. 2.主表的汇总字段是汇总货币类型,但是 ...

  9. Unity协程Coroutine使用总结和一些坑

    原文摘自 Unity协程Coroutine使用总结和一些坑 MonoBehavior关于协程提供了下面几个接口: 可以使用函数或者函数名字符串来启动一个协程,同时可以用函数,函数名字符串,和Corou ...

  10. keycode值对照表

    转载自:https://segmentfault.com/a/1190000005828048 字母和数字键的键码值(keyCode) 按键 键码 按键 键码 按键 键码 按键 键码 A 65 J 7 ...