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. Unity3d 屏幕空间人体皮肤知觉渲染&次表面散射Screen-Space Perceptual Rendering & Subsurface Scattering of Human Skin

    之前的人皮渲染相关 前篇1:unity3d Human skin real time rendering 真实模拟人皮实时渲染 前篇2:unity3d Human skin real time ren ...

  2. ubuntu下使用ngrok外网映射

    好久之前想搞明白这个事情,可是就是不知道这个词叫外网映射,所以也一直不知怎么做,在慕课网看用java开发微信公众号的时候教程里提到了外网映射,查了一些资料终于把本地给映射到外网了,直接变成了80端口, ...

  3. codevs 1421 秋静叶&秋穣子(树上DP+博弈)

    1421 秋静叶&秋穣子   题目描述 Description 在幻想乡,秋姐妹是掌管秋天的神明,作为红叶之神的姐姐静叶和作为丰收之神的妹妹穰子.如果把红叶和果实联系在一 起,自然会想到烤红薯 ...

  4. CentOS添加swap分区

    在多个VPS上尝试. 1.进入目录 cd /var/ 2.获取要增加的SWAP文件块(这里以1GB为例) dd if=/dev/zero of=swapfile bs=1024 count=10383 ...

  5. MySQL高可用性大杀器之MHA | 火丁笔记

    MySQL高可用性大杀器之MHA | 火丁笔记 MySQL高可用性大杀器之MHA

  6. poj 3159 Candies

    Candies Time Limit: 1500MS   Memory Limit: 131072K Total Submissions: 25776   Accepted: 7033 Descrip ...

  7. reloadData should be in main thread

    reloadData should be called in main thread, so if you call it in work thread, you should call it as ...

  8. HDU 4432 Sum of divisors (进制模拟)

    三个小函数 getdiv();        求因子 getsum();     求平方和 change();     转换成该进制 #include <cstdio> #include ...

  9. AIX操作oracle

    oracle:出现下述错误,无法连接用户. ORA-01034: ORACLE not available ORA-27101: shared memory realm does not exist ...

  10. config 数据库字符串的读取、修改 分类: WebForm 2014-12-16 10:24 203人阅读 评论(0) 收藏

    config数据库字符串: <connectionStrings>   <add name="MyWebDataString" connectionString= ...