【题意】
如指令所示:
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本书的编号。

【题解】
伸展树
借助伸展树翻转后中序遍历不变来维护书架上书的顺序。
第一步,用二分的方法建一棵尽量平衡的树。
对于1,(如果不在第1本)把s放在树的最左孩子的左边,它就会是第一个遍历到的,即第1本;
对于2,(如果不在第n本)把s放在树的最右孩子的右边,它会是最后一个遍历到的,即第n本;
对于3,找到与s交换的那一本,硬插在它与它的孩子间。在左边位在它上一本,在右边为在它下一本;
对于4,问s的中序遍历。只需将s转到根,它左孩子的个数+1即为它的中序遍历编号;
对于5,问中序遍历第s的是谁。对于节点x,看看是在它的左子树还是右子树。

【注意与错误】
1、建树时,要注意子树不能包含自己,即build(l,mid-1),build(mid+1,r);
2、书本的实际编号 与 树上节点的编号不同,需要记录其转换关系;
3、(del函数中发现)注意数据转移过程中的顺序,不要删掉了一些后面有用的东西,导致转移中断;
4、(del函数中发现)我们的删除总是把节点旋到根来处理的,记得所有操作都要更改根的标记;
5、(find_abovenum函数中发现)中序遍历也好,求排名也好,要在左子树的数量上+1,否则会出现0;
6、任何树的操作最好放到根来做。否则相关节点的c会不能便捷地求出,因为在树的下部不好更新上部分,除非把更新的节点做一次splay旋到根,同时对整棵树进行更新。

【收获】
可以自制小数据,有针对性的试验某个指令,在合起来测试。避免在一个样例中出现多个不能保证正确性的命令,而无从下手。

【代码】

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;int n;
int a[80010];
struct node
{int d,c,f,son[2];
}tr[80010];int len=0,root,pos[80010];//注意树上节点的编号与实际编号的区别  pos[x]实际编号对应的树上的节点编号 void update(int x)
{tr[x].c=tr[tr[x].son[0]].c+tr[tr[x].son[1]].c+1;
}void clean(int x)
{tr[x].c=tr[x].f=tr[x].son[0]=tr[x].son[1]=0;
}int build(int l,int r)
{if(l>r) return 0;int mid,x;mid=(l+r)/2;x=++len;tr[x].d=a[mid];pos[a[mid]]=x;if(l==r){tr[x].son[0]=tr[x].son[1]=0;update(x);return x;}int lc,rc;lc=tr[x].son[0]=build(l,mid-1);rc=tr[x].son[1]=build(mid+1,r);if(lc!=0) tr[lc].f=x;if(rc!=0) tr[rc].f=x;update(x);return x;
}void rotate(int x,int w)
{int f=tr[x].f,ff=tr[f].f;int r,R;r=tr[x].son[w];R=f;tr[R].son[1-w]=r;if(r!=0) tr[r].f=R;r=x;R=ff;if(tr[ff].son[0]==f) tr[R].son[0]=r;else tr[R].son[1]=r;tr[r].f=R;r=f;R=x;tr[R].son[w]=r;tr[r].f=R;update(f);update(x);
}void splay(int x,int rt)
{while(tr[x].f!=rt){int f=tr[x].f,ff=tr[f].f;if(tr[f].f==rt){if(tr[f].son[0]==x) rotate(x,1);else rotate(x,0);}if(tr[ff].son[0]==f&&tr[f].son[0]==x){rotate(f,1);rotate(x,1);}else if(tr[ff].son[1]==f&&tr[f].son[1]==x){rotate(f,0);rotate(x,0);}else if(tr[ff].son[0]==f&&tr[f].son[1]==x){rotate(x,0);rotate(x,1);}else if(tr[ff].son[1]==f&&tr[f].son[0]==x){rotate(x,1);rotate(x,0);}}if(rt==0) root=x;
}void del(int x)
{splay(x,0);if(tr[x].son[0]==0&&tr[x].son[1]==0){root=0;clean(x);}else if(tr[x].son[0]==0&&tr[x].son[1]!=0){root=tr[x].son[1];tr[root].f=0;clean(x);}else if(tr[x].son[0]!=0&&tr[x].son[1]==0){root=tr[x].son[0];tr[root].f=0;clean(x);}else if(tr[x].son[0]!=0&&tr[x].son[1]!=0){int p=tr[x].son[0];while(tr[p].son[1]!=0) p=tr[p].son[1];splay(p,x);int r,R;r=tr[x].son[1];R=p;tr[R].son[1]=r;tr[r].f=R;root=p;tr[root].f=0;clean(x);update(p);}
}int find_head()
{int x=root;while(tr[x].son[0]!=0) x=tr[x].son[0];return x;
}int find_tail()
{int x=root;while(tr[x].son[1]!=0) x=tr[x].son[1];return x;
}int find_bookid(int k)//查询中序遍历第k的节点编号
{int x=root;while(1){int lc=tr[x].son[0],rc=tr[x].son[1];if(k<=tr[lc].c){x=lc;}else if(k>tr[lc].c+1){k-=tr[lc].c+1;x=rc;}else break;}return x;
}int find_abovenum(int x)//查询x的中序遍历编号
{splay(x,0);return tr[tr[x].son[0]].c+1;
}char opt[10];
int main()
{int Q;scanf("%d%d",&n,&Q);for(int i=1;i<=n;i++){scanf("%d",&a[i]);}root=build(1,n);while(Q--){int s,t,x,R,r,ans;scanf("%s",opt);if(opt[0]=='T'){scanf("%d",&s);s=pos[s];x=find_head();if(x==s) continue;del(s);splay(x,0);R=x;r=s;tr[R].son[0]=r;tr[r].f=R;update(s);update(x);}else if(opt[0]=='B'){scanf("%d",&s);s=pos[s];x=find_tail();if(x==s) continue;del(s);splay(x,0);R=x;r=s;tr[R].son[1]=r;tr[r].f=R;update(s);update(x);}else if(opt[0]=='I'){scanf("%d%d",&s,&t);s=pos[s];if(t==-1){x=find_bookid(find_abovenum(s)+t);del(s);splay(x,0);R=s;r=tr[x].son[0];tr[R].son[0]=r;tr[r].f=R;R=x;r=s;tr[R].son[0]=r;tr[r].f=R;update(s);update(x);}else if(t==1){x=find_bookid(find_abovenum(s)+t);del(s);splay(x,0);R=s;r=tr[x].son[1];tr[R].son[1]=r;tr[r].f=R;R=x;r=s;tr[R].son[1]=r;tr[r].f=R;update(s);update(x);}}else if(opt[0]=='A'){scanf("%d",&s);s=pos[s];splay(s,0);ans=find_abovenum(s)-1;//要减去1,因为求的是上面的书的本数 printf("%d\n",ans);}else if(opt[0]=='Q'){scanf("%d",&s);ans=tr[find_bookid(s)].d;printf("%d\n",ans);}}return 0;
}

bzoj1861 [Zjoi2006]Book 书架相关推荐

  1. bzoj1861[Zjoi2006]Book 书架

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

  2. BZOJ1861: [Zjoi2006]Book 书架

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

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

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

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

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

  5. 【Splay】【ZJOI2006】书架

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

  6. BZOJ 1861 ZJOI2006 Book 书架 Splay

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

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

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

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

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

  9. BZOJ ac100题存档

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

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

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

最新文章

  1. android studio文件风格,Android Studio构建风格 – 如何拥有不同风格的相同源文件
  2. 基于遗传算法优化的BP神经网络的 非线性函数拟合
  3. SAP Fiori element框架template的框架加载逻辑
  4. SQL注入漏洞全接触--高级篇
  5. STL源码剖析 第二次温习 细节审核
  6. 行程日志2010-03-16沙井一村(1)
  7. Github图片无法打开的问题解决【2020.07.20更新】
  8. ToDesk 远程控制软件---修电脑的好帮手
  9. Java | 内部类的实例化
  10. 电脑右下角自动弹出窗口(弹窗)
  11. 产品介绍丨世炬5G一体化基站
  12. 怎样更改itunes备份位置_什么是iTunes备份文件?
  13. java gson解析JSON
  14. 卫星导航开源代码汇总
  15. 指针式万用表测量电容
  16. python教程-马哥教育官网-专业Linux培训班,Python培训机构
  17. 百度地图定位到了非洲的问题
  18. 北京住房公积金提取(取消)指南
  19. Component属性
  20. csv文件导入Mysql

热门文章

  1. resttemplate 发送get请求
  2. 利用matlab构建自己的colormap(色彩搭配)
  3. c语言中shift的作用,Shift是什么意思?Shift键都有什么作用?
  4. Google Earth Engine(GEE)——NASA-USDA增强型SMAP全球土壤水分数据以10公里的空间分辨率提供全球的土壤水分信息
  5. Java Socket 网络编程
  6. 题目1026 c语言,1026 程序运行时间——C/C++实现
  7. openwrt修改默认网关地址_修改宇视摄像机IP地址的方法
  8. hdu 2881 Jack's struggle(DP)
  9. harmonyOS hdc配置以及自动签名
  10. 想找个娇小可爱的女孩