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
 

Source

Zjoi2006
【分析】
基本是裸的splay,
找编号弄一个映射过去就好了。
动态内存分配大法好....
 /*
唐代李白
《江夏别宋之悌》
楚水清若空,遥将碧海通。人分千里外,兴在一杯中。
谷鸟吟晴日,江猿啸晚风。平生不下泪,于此泣无穷.
*/
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <vector>
#include <utility>
#include <iomanip>
#include <string>
#include <cmath>
#include <queue>
#include <assert.h>
#include <map>
#include <ctime>
#include <cstdlib>
#include <stack>
#include <set>
#define LOCAL
const int INF = 0x7fffffff;
const int MAXN = + ;
const int maxnode = * + * ;
const int MAXM = + ;
const int MAX = ;
using namespace std;
struct Node {
int siz;
int val;//val代表数的编号
Node *parent, *ch[]; int cmp(){
if (parent->ch[] == this) return ;
else return ;
}
}*root, mem[MAXN * ], *book[MAXN * ];//book为编号映射
int tot, n, m; Node *NEW(int val){
Node *t = new Node;
t->val = val;
t->siz = ;
t->parent = t->ch[] = t->ch[] = NULL;
return t;
}
void update(Node *&t){
if (t == NULL) return;
t->siz = ;
if (t->ch[] != NULL) t->siz += t->ch[]->siz;
if (t->ch[] != NULL) t->siz += t->ch[]->siz;
return ;
}
void rotate(Node *t, int d){
if (t->parent == NULL) return;//根就没必要旋转了 Node *p = t->parent;
p->ch[d ^ ] = t->ch[d];
if (t->ch[d] != NULL) t->ch[d]->parent = p;
t->parent = p->parent;
if (p->parent != NULL){
if (p->parent->ch[] == p) p->parent->ch[] = t;
else if (p->parent->ch[] == p) p->parent->ch[] = t;
}
t->ch[d] = p;
p->parent = t;
update(p);
update(t);
if (root == p) root = t;
}
//将x旋转到y的子树,自己都不知道转成什么样子了...
void splay(Node *x, Node *y){
while (x->parent != y){
if (x->parent->parent == y){
rotate(x, x->cmp() ^ );
}else{
Node *t = x->parent;
//之字形
if (t->ch[t->cmp() ^ ] == x) rotate(x, x->cmp()^);
else rotate(t, t->cmp() ^ );
rotate(x, x->cmp() ^ );
}
update(x);
}
update(x);
}
//找到第k小然后splay上去
void find(Node *y, int k){
Node *t = root;
while (){
if (t->siz == ) break;
int c = (t->ch[] == NULL ? : t->ch[]->siz);
if (c + == k) break;
if (c >= k ) t = t->ch[];
else {t = t->ch[], k -= c + ;}
}
splay(t, y);
}
//插入到第pos个位置
void insert(Node *t, int pos, int val){
find(NULL, pos + );
find(root, pos + ); Node *p = NEW(val);
root->ch[]->ch[] = p;
p->parent = root->ch[];
book[val] = p;
splay(p, NULL);
}
//找到元素val在t中是第几个
int kth(Node *t, int val){
splay(book[val], NULL);
return root->ch[]->siz; //不要忘了还有个INF在前面,哈哈哈
}
void erase(Node *t, int pos){
find(NULL, pos);
find(root, pos + );
Node *p = root->ch[]->ch[];
p->parent = NULL;
root->ch[]->ch[] = NULL;
delete(p);
} void init(){
tot = ;
root = NULL;
root = NEW(-INF);
root->ch[] = NEW(INF);
root->ch[]->parent = root;
update(root); //find(NULL, 2);
//printf("%d", root->val);
scanf("%d%d", &n, &m);
for (int i = ; i <= n; i++){
int t;
scanf("%d", &t);
insert(root, i - , t);
}
//printf("%d", kth(root, 10));
}
void work(){
for (int i = ; i <= m; i++){
char str[];
scanf("%s", str);
if (str[] == 'T'){//无论任何时候都有n本书
int t;
scanf("%d", &t);
erase(root, kth(root, t));
insert(root, , t);
}else if (str[] == 'B'){
int t;
scanf("%d", &t);
erase(root, kth(root, t));
insert(root, n - , t);
}else if (str[] == 'A'){
int t;
scanf("%d", &t);
printf("%d\n", kth(root, t) - );
}else if (str[] == 'Q'){
int t;
scanf("%d", &t);
find(NULL, t + );
printf("%d\n", root->val);
}else{//修改
int s, t;
scanf("%d%d", &s, &t);
if (t == ) continue;//不动
int tmp = kth(root, s);//记录s当前的位置
erase(root, tmp);
if (t == -) insert(root, tmp - , s);
else insert(root, tmp, s);
}
}
} int main(){ init();
work();
return ;
}

【BZOJ1861】【splay】Book 书架的更多相关文章

  1. [BZOJ1861][Zjoi2006]Book 书架

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

  2. bzoj1861 [Zjoi2006]Book 书架 splay

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

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

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

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

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

  5. BZOJ1861:[ZJOI2006]书架

    浅谈\(splay\):https://www.cnblogs.com/AKMer/p/9979592.html 浅谈\(fhq\)_\(treap\):https://www.cnblogs.com ...

  6. BZOJ1861:[ZJOI2006]书架——题解

    http://www.lydsy.com/JudgeOnline/problem.php?id=1861 (题面复制于洛谷) 题目描述 小T有一个很大的书柜.这个书柜的构造有些独特,即书柜里的书是从上 ...

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

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

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

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

  9. BZOJ1861[ZJOI2006]Book书架

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

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

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

随机推荐

  1. 制作手机浏览器显示格式的HTML页面

    最近要推出手机支持访问的HTML页面效果,而这在制作手机页面的过程中状况连连. 主要一下就我制作的工程中所遇的问题说明一下: 1. 改掉HTML页面声明:(以往大部分页面都是HTML4.0的声明) 还 ...

  2. 第二十三章、软件安装: RPM, SRPM 与 YUM 功能

    SRPM 的使用 : rpmbuild 包含Source code 的 SRPM 新版的 rpm 已经将 RPM 与 SRPM 的命令分开了,SRPM 使用的是 rpmbuild 这个命令,而不是 r ...

  3. tabhost中activity跳转动画不显示的解决办法

    [1]如果是tabhost中的activity跳到其他的activity,用这篇blog的方法即可 http://blog.sina.com.cn/s/blog_8db8914301010t31.ht ...

  4. 「S-A-L-T-A」项目失败总结!

    前言: 从2013年8月20日进入这个项目开始,到现在12月12日. 从项目详细设计开始,到现在连SI2阶段的疏通测试都没有完成! (现在,这个项目好像已经不需要我们再做下去了...) 项目失败原因总 ...

  5. Hibernate配置文件详解

    Hibernate配置方式 Hibernate给人的感受是灵活的,要达到同一个目的,我们可以使用几种不同的办法.就拿Hibernate配置来说,常用的有如下三种方式,任选其一. 在 hibernate ...

  6. 设置U盘为第一启动顺序

    本文转载:http://u.diannaodian.com/Article/1004.html 盘安装系统的首要步骤就是设置U盘为第一启动顺序.下面电脑店官网就来说说到底如何来设置U盘启动顺序吧.   ...

  7. Java学习笔记六(I/O流)

    1.介绍 在实际开发过程中经常会用到数据的输入/输出操作,本篇博客着重分析一下,java中经经常使用到的有关IO操作的类.而在java中能够将经常使用的流分为两个部分:字节流和字符流. 1.流的抽象基 ...

  8. 使用jsdoc-toolkit来自动生成js api文档

    近来前端组小盆友开发的类库越来越多,很多情况下彼此不知道写了些什么方法,为了更好的合作提高工作效率,找了个比较好的api文档生成方法.使用jsdoc-toolkit来自动生成js api文档. 一.  ...

  9. android 40 Io编程

    Io编程:内存卡和sd卡.字符串存入内存卡然后读出来. activity: package com.sxt.day06_06; import java.io.FileInputStream; impo ...

  10. JAVA异常的捕获与抛出原则

    在可能会出现exception的地方,要使用try-catch或者throws或者两者都要.我的判断依据是:如果对可能出现的exception不想被外部(方法的调用者)知道,就在方法内部try-cat ...