1861: [Zjoi2006]Book 书架

Time Limit: 4 Sec  Memory Limit: 64 MB
Submit: 1396  Solved: 803
[Submit][Status][Discuss]

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

[Submit][Status][Discuss]


  将用Splay按照下标来建树,另外用一个数组来记录编号为i的书在Splay中的位置(指针)。

  Top、Bottom和Insert操作就把该节点删掉,然后重新取出来,然后插到对应的位置。

  Ask操作把对应节点伸展到根,然后求左子树的大小。Query操作就求K小值就行了。

Code

 /**
* bzoj
* Problem#1861
* Accepted
* Time:1280ms
* Memory:3464k
*/
#include<iostream>
#include<fstream>
#include<sstream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<ctime>
#include<cctype>
#include<cmath>
#include<algorithm>
#include<stack>
#include<queue>
#include<set>
#include<map>
#include<vector>
using namespace std;
typedef bool boolean;
#define smin(a, b) (a) = min((a), (b))
#define smax(a, b) (a) = max((a), (b))
template<typename T>
inline void readInteger(T& u){
char x;
int aFlag = ;
while(!isdigit((x = getchar())) && x != '-' && x != -);
if(x == -) return;
if(x == '-'){
x = getchar();
aFlag = -;
}
for(u = x - ''; isdigit((x = getchar())); u = (u << ) + (u << ) + x - '');
ungetc(x, stdin);
u *= aFlag;
} template<typename T>
class SplayNode{
public:
T data;
int s;
SplayNode* next[];
SplayNode* father;
SplayNode(T data, SplayNode* father):data(data), father(father), s(){
memset(next, , sizeof(next));
}
inline void maintain(){
this->s = ;
for(int i = ; i < ; i++)
if(next[i] != NULL)
s += next[i]->s;
}
int which(SplayNode* p){
return (next[] == p) ? () : ();
}
}; template<typename T>
class Splay{
protected:
inline static void rotate(SplayNode<T>*& node, int d){
SplayNode<T> *father = node->father;
SplayNode<T> *newRoot = node->next[d ^ ];
node->next[d ^ ] = newRoot->next[d];
node->father = newRoot;
newRoot->next[d] = node;
newRoot->father = father;
if(node->next[d ^ ] != NULL) node->next[d ^ ]->father = node;
if(father != NULL) father->next[father->which(node)] = newRoot;
node->maintain();
node->father->maintain();
} static SplayNode<T>* findKth(SplayNode<T>*& node, int k){
int ls = (node->next[] != NULL) ? (node->next[]->s) : ();
if(k == ls + ) return node;
if(k <= ls) return findKth(node->next[], k);
return findKth(node->next[], k - ls - );
} public:
SplayNode<T>* root; Splay():root(NULL){ } inline void splay(SplayNode<T>*& node, SplayNode<T>* father){
while(node->father != father){
SplayNode<T>* f = node->father;
int fd = f->which(node);
SplayNode<T>* ff = f->father;
if(ff == father){
rotate(f, fd ^ );
break;
}
int ffd = ff->which(f);
if(fd == ffd){
rotate(ff, ffd ^ );
rotate(f, fd ^ );
}else{
rotate(f, fd ^ );
rotate(ff, ffd ^ );
}
}
if(father == NULL)
root = node;
} inline SplayNode<T>* findKth(int k, SplayNode<T>* father){
if(root == NULL || k < || k > root->s) return NULL;
SplayNode<T>* res = findKth(root, k);
splay(res, father);
return res;
} inline void insert(T data, int index){
if(root == NULL){
root = new SplayNode<T>(data, NULL);
return;
}
SplayNode<T>* added;
if(index <= ){
findKth(, NULL);
added = root->next[] = new SplayNode<T>(data, root);
}else if(index >= root->s + ){
findKth(root->s, NULL);
added = root->next[] = new SplayNode<T>(data, root);
}else if(index == root->s){
findKth(index, NULL);
findKth(index - , root);
added = new SplayNode<T>(data, root);
added->next[] = root->next[];
root->next[]->father = added;
root->next[] = added;
}else{
findKth(index - , NULL);
findKth(index + , root);
SplayNode<T>* node = root->next[]->next[];
added = node->next[] = new SplayNode<T>(data, node);
}
splay(added, NULL);
} inline void remove(SplayNode<T>* node){
splay(node, NULL);
SplayNode<T>* maxi = node->next[];
if(maxi == NULL){
root = node->next[];
if(node->next[] != NULL) node->next[]->father = NULL;
delete node;
return;
}
while(maxi->next[] != NULL) maxi = maxi->next[];
splay(maxi, node);
maxi->next[] = node->next[];
if(node->next[] != NULL) node->next[]->father = maxi;
maxi->father = NULL;
delete node;
root = maxi;
maxi->maintain();
} }; int n, m;
Splay<int> s;
SplayNode<int>** books; inline void init(){
readInteger(n);
readInteger(m);
books = new SplayNode<int>*[(const int)(n + )];
for(int i = , a; i <= n; i++){
readInteger(a);
s.insert(a, i);
books[a] = s.root;
}
} inline void solve(){
char cmd[];
int a, b;
while(m--){
scanf("%s", cmd);
readInteger(a);
if(cmd[] == 'T'){
s.remove(books[a]);
s.insert(a, );
books[a] = s.root;
}else if(cmd[] == 'B'){
s.remove(books[a]);
s.insert(a, n);
books[a] = s.root;
}else if(cmd[] == 'I'){
readInteger(b);
if(b == ) continue;
s.splay(books[a], NULL);
int r = (s.root->next[] == NULL) ? () : (s.root->next[]->s);
s.remove(books[a]);
s.insert(a, r + + b);
books[a] = s.root;
}else if(cmd[] == 'A'){
s.splay(books[a], NULL);
int r = (s.root->next[] == NULL) ? () : (s.root->next[]->s);
printf("%d\n", r);
}else if(cmd[] == 'Q'){
SplayNode<int> *node = s.findKth(a, NULL);
printf("%d\n", node->data);
}
}
} int main(){
init();
solve();
return ;
}

[题解]bzoj 1861 Book 书架 - Splay的更多相关文章

  1. [bzoj 1861][zjoi2006] 书架

    传送门 Description 1. Top S--表示把编号为S的书放在最上面. 2. Bottom S--表示把编号为S的书放在最下面. 3. Insert S T--T∈{-1,0,1},若编号 ...

  2. BZOJ 1861书架

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

  3. [BZOJ3523][Poi2014]KLO-Bricks——全网唯一 一篇O(n)题解+bzoj最优解

    Description 有n种颜色的砖块,第i种颜色的砖块有a[i]个,你需要把他们放成一排,使得相邻两个砖块的颜色不相同,限定第一个砖块的颜色是start,最后一个砖块的颜色是end,请构造出一种合 ...

  4. 洛谷 题解 P2676 【超级书架】

    题解 P2676 [超级书架] 这题就只是一个从大到小的排序而已,用"sort"函数 再用"while"判断奶牛塔的高度是否比书架高度要高 送上代码: #inc ...

  5. BZOJ 1861: [Zjoi2006]Book 书架 splay

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

  6. BZOJ 1861: [Zjoi2006]Book 书架 (splay)

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

  7. BZOJ 1861: [Zjoi2006]Book 书架 | SPlay 板题

    #include<cstdio> #include<algorithm> #include<cstring> #define N 80010 #define whi ...

  8. BZOJ 1861 [Zjoi2006]Book 书架 ——Splay

    [题目分析] 模板题目. 首尾两个虚拟结点,十分方便操作. [代码] #include <cstdio> #include <cstring> #include <cma ...

  9. BZOJ 1861: [Zjoi2006]Book 书架

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

随机推荐

  1. .Net 中的反射(查看基本类型信息)

    反射概述 和Type类 1.反射的作用 简单来说,反射提供这样几个能力:1.查看和遍历类型(及其成员)的基本信息和程序集元数据(metadata):2.迟绑定(Late-Binding)方法和属性.3 ...

  2. WiresShark 一站式学习

    按照国际惯例,从最基本的说起. 抓取报文: 下载和安装好Wireshark之后,启动Wireshark并且在接口列表中选择接口名,然后开始在此接口上抓包.例如,如果想要在无线网络上抓取流量,点击无线接 ...

  3. 利用线程把文本文件填充到richTextBox;防止导入大文本文件窗口假死现象

    private void btnDr_Click(object sender, EventArgs e) { richTextBox1.Text = ""; //richTextB ...

  4. UIScrollView代理方法

    手拖拽后会调用 - (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView [scrollView setContentOffset ...

  5. USACO Section 1.2 Transformations 解题报告

    题目 题目描述 一块 N x N正方形的黑白瓦片的图案要被转换成新的正方形图案. 写一个程序来找出将原始图案按照以下列转换方法转换成新图案的最小方式: 转 90 度:图案按顺时针转 90 度. 转 1 ...

  6. zencart 具体页面调用规则: $body_code变量解析

    zencart $body_code变量解析 修改centerColumn 可以修改中间产品方框的大小 2.2.5 .BODY文件在这个文件生效 require($body_code) include ...

  7. 关于Bean\Entity\Model\POJO的一些个人理解

    本文没有长篇累牍的,严格的,标准的表述,只是我在开发过程中,读书过程中的一些个人理解,可能不太准备,但是我觉得应该是最方便初学者理解的吧? 一.Bean 对于Bean而言,我的理解是只要是Java的类 ...

  8. JS对象引用

    对象和函数都是引用的关系(改变后者会改变前者) 但是下面这个列子情况不一样了.刚开始的时候 B 引用了 A的地址,后来B又重新赋值,新占了一个地址,A   B俩的关系已经脱离. 那么有的时候,我们只有 ...

  9. Tickets 基础DP

    Tickets Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)Total Sub ...

  10. 使用strace+pstack利器分析程序性能

    引言 有时我们需要对程序进行优化.减少程序响应时间.除了一段段地对代码进行时间复杂度分析,我们还有更便捷的方法吗? 若能直接找到影响程序运行时间的函数调用,再有针对地对相关函数进行代码分析和优化,那相 ...