bzoj1861[ZJOI2006]书架

题目描述

小T有一个很大的书柜。这个书柜的构造有些独特,即书柜里的书是从上至下堆放成一列。她用1到n的正整数给每本书都编了号。

小T在看书的时候,每次取出一本书,看完后放回书柜然后再拿下一本。由于这些书太有吸引力了,所以她看完后常常会忘记原来是放在书柜的什么位置。不过小T的记忆力是非常好的,所以每次放书的时候至少能够将那本书放在拿出来时的位置附近,比如说她拿的时候这本书上面有X本书,那么放回去时这本书上面就只可能有X-1、X或X+1本书。

当然也有特殊情况,比如在看书的时候突然电话响了或者有朋友来访。这时候粗心的小T会随手把书放在书柜里所有书的最上面或者最下面,然后转身离开。

久而久之,小T的书柜里的书的顺序就会越来越乱,找到特定的编号的书就变得越来越困难。于是她想请你帮她编写一个图书管理程序,处理她看书时的一些操作,以及回答她的两个提问:(1)编号为X的书在书柜的什么位置;(2)从上到下第i本书的编号是多少。

输入输出格式

输入格式:

第一行有两个数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本书的编号。

输出格式:

对于每一条Ask或Query语句你应该输出一行,一个数,代表询问的答案。

输入输出样例

输入样例#1: 复制

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
输出样例#1: 复制

2
9
9
7
5
3

说明

100%的数据,n,m <= 80000

sol:虽然是模板题,但由于本人是幼儿园水平,十分无奈的看题解了(确实有很多细节写不出来)

最重要的两个变量:

int Pos[N] 标号为i的书在树上的位置

int Id[N] 树上位置为i的节点在书架上的标号[1,n]

然后我还是不会把一个节点移到任意一个位置(多多指教)

对于置顶:把当前节点Splay为根后,把左子树串到后继节点的左子树即可,置底同理

对于移动,只要交换两个点的Pos和Id就可以了,多多Splay防T

巨丑无比的代码

#include <bits/stdc++.h>
using namespace std;
typedef int ll;
inline ll read()
{
ll s=;
bool f=;
char ch=' ';
while(!isdigit(ch))
{
f|=(ch=='-'); ch=getchar();
}
while(isdigit(ch))
{
s=(s<<)+(s<<)+(ch^); ch=getchar();
}
return (f)?(-s):(s);
}
#define R(x) x=read()
inline void write(ll x)
{
if(x<)
{
putchar('-'); x=-x;
}
if(x<)
{
putchar(x+''); return;
}
write(x/);
putchar((x%)+'');
return;
}
#define W(x) write(x),putchar(' ')
#define Wl(x) write(x),putchar('\n')
const int N=,inf=0x3f3f3f3f;
int n,Q;
namespace Pht
{
int Points=,Root;
int Child[N][],Parent[N];
int Pos[N];//标号为i的书在树上的位置
int Id[N];//树上位置为i的节点在书架上的标号[0,n+1]
int Size[N]; inline void Init();
inline int Check(int x);
inline void PushUp(int x);
inline void Rotate(int x);
inline void Splay(int At,int To);
inline void Insert(int Val);
inline void Above(int Val);
inline void Below(int Val);
inline void Move(int Val,int Delta);
inline int Ask_Rank(int Val);
inline int Ask_Kth(int K);
inline void Solve(); inline void Init()
{
int i;
for(i=;i<=n;i++) Insert(read());
}
inline int Check(int x)
{
return (Child[Parent[x]][]==x)?:;
}
inline void PushUp(int x)
{
Size[x]=Size[Child[x][]]+Size[Child[x][]]+;
Pos[Id[Child[x][]]]=Child[x][];
Pos[Id[Child[x][]]]=Child[x][];
}
inline void Rotate(int x)
{
int y,z,oo;
y=Parent[x];
z=Parent[y];
oo=Check(x);
Child[y][oo]=Child[x][oo^]; Parent[Child[x][oo^]]=y;
Child[z][Check(y)]=x; Parent[x]=z;
Child[x][oo^]=y; Parent[y]=x;
PushUp(x);
PushUp(y);
}
inline void Splay(int At,int To)
{
while(Parent[At]!=To)
{
int Father=Parent[At];
if(Parent[Father]==To)
{
Rotate(At);
}
else if(Check(At)==Check(Father))
{
Rotate(Father); Rotate(At);
}
else
{
Rotate(At); Rotate(At);
}
}
Pos[Id[At]]=At;
if(To==) Root=At;
}
inline void Insert(int Val)
{
int Now=Root,Par=;
while(Now)
{
Par=Now;
Now=Child[Now][];
}
Now=++Points;
if(Par) Child[Par][]=Now;
Child[Now][]=Child[Now][]=;
Parent[Now]=Par;
Size[Now]=;
Pos[Val]=Now;
Id[Now]=Val;
Splay(Now,);
}
// inline void Remove(int Val)
// {
// int P1=Ask_Kth(Val-1),P2=Ask_Kth(Val+1);
// Splay(P1,0);
// Splay(P2,P1);
// int Pos=Child[P2][0];
// Child[P2][0]=0;
// Size[Pos]=Parent[Pos]=Id[Pos]=0;
// Splay(P2,0);
// }
inline void Above(int Val)
{
Splay(Pos[Val],);
if(!Child[Root][]) return; //最上面了
if(!Child[Root][]) //下面没了直接把左儿子移到右儿子就可以了
{
Child[Root][]=Child[Root][];
Child[Root][]=;
}
else
{
int Now=Child[Root][];
while(Child[Now][]) Now=Child[Now][];
Parent[Child[Root][]]=Now; //把左儿子串到后继节点上,中序遍历仍然正确
Child[Now][]=Child[Root][];
Child[Root][]=;
Splay(Child[Now][],); //从新串的节点更新一遍
}
}
inline void Below(int Val)
{
Splay(Pos[Val],);
if(!Child[Root][]) return;
if(!Child[Root][])
{
Child[Root][]=Child[Root][]; Child[Root][]=;
}
else
{
int Now=Child[Root][];
while(Child[Now][]) Now=Child[Now][]; //前驱节点
Parent[Child[Root][]]=Now;
Child[Now][]=Child[Root][];
Child[Root][]=;
Splay(Child[Now][],);
}
}
inline void Move(int Val,int Delta)
{
Splay(Pos[Val],);
if(!Delta) return;
else if(Delta==)
{
int Upper=Child[Root][],tmp=Pos[Val];
while(Child[Upper][]) Upper=Child[Upper][];
swap(Pos[Val],Pos[Id[Upper]]);
swap(Id[tmp],Id[Upper]);
}
else
{
int Lower=Child[Root][],tmp=Pos[Val];
while(Child[Lower][]) Lower=Child[Lower][];
swap(Pos[Val],Pos[Id[Lower]]);
swap(Id[tmp],Id[Lower]);
}
}
inline int Ask_Rank(int Val)
{
Splay(Pos[Val],);
return Size[Child[Root][]];
}
inline int Ask_Kth(int K)
{
int Now=Root;
for(;;)
{
if(Size[Child[Now][]]>=K)
{
Now=Child[Now][];
}
else if(Size[Child[Now][]]+==K)
{
return Now;
}
else
{
K-=(Size[Child[Now][]]+);
Now=Child[Now][];
}
}
}
inline void Solve()
{
int x;
char S[];
Init();
while(Q--)
{
scanf("%s",S+);
switch (S[])
{
case 'T':
Above(read());
break;
case 'B':
Below(read());
break;
case 'I':
R(x);
Move(x,read());
break;
case 'A':
Wl(Ask_Rank(read()));
break;
case 'Q':
Wl(Id[Ask_Kth(read())]);
break;
}
}
}
}
int main()
{
int i;
R(n); R(Q);
Pht::Solve();
return ;
}
/*
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
output
2
9
9
7
5
3
*/

bzoj1861的更多相关文章

  1. [BZOJ1861][Zjoi2006]Book 书架

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

  2. bzoj1861 书架

    bzoj1861 书架 原题链接 神题... 先吐槽洛谷的样例 10 10 1 3 2 7 5 8 10 4 9 6 Query 3 Top 5 Ask 6 Bottom 3 Ask 3 Top 6 ...

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

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

  4. BZOJ1861——book

    就是给你一摞书,然后又询问第k大,编号为x的书是第几大,然后修改书的位置 splay模板题...然而我还是不会,,,又遇到lrj的书的坑了,rj的书里没有father,顿时弄得我ask不会搞了 注意合 ...

  5. BZOJ-1861 Book 书架 Splay

    1861: [Zjoi2006]Book 书架 Time Limit: 4 Sec Memory Limit: 64 MB Submit: 1010 Solved: 588 [Submit][Stat ...

  6. BZOJ1861[ZJOI2006]Book书架

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

  7. 【BZOJ1861】【splay】Book 书架

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

  8. [BZOJ1861][ZJOI2006]书架

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

  9. BZOJ1861[Zjoi2006]书架——非旋转treap

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

随机推荐

  1. windows下数据挖掘相关包numpy、pandas的安装

    安装Anaconda的绕道 这里介绍如何在windows下安装numpy/scipy/matplotlib/pandas/scikit_learn等数据分析相关包 相关环境: win7 64位 pyt ...

  2. C语言中数组变量和指针变量

    指针变量为什么需要类型? 数组变量和指针变量在使用sizeof时不同,sizeof(数组变量)是数组长度,sizeof(指针变量)是存储int的字节长度4或者8(64bit). 数组变量在参数传递中, ...

  3. CRectTracker类的使用

    CRectTracker(俗称“橡皮筋”类)是一个非常有意思的类.你在Windows中经常看到这样的情况:它可以用做显示边界,你也可以扽它的八个角用来放大缩小,或做框选使用.如何通过编程来实现这种功能 ...

  4. iptables防火墙规则的添加、删除、修改、保存

    原文地址:https://blog.csdn.net/educast/article/details/52093390 本文介绍iptables这个Linux下最强大的防火墙工具,包括配置iptabl ...

  5. UVA 10820 欧拉函数模板题

    这道题就是一道简单的欧拉函数模板题,需要注意的是,当(1,1)时只有一个,其他的都有一对.应该对欧拉函数做预处理,显然不会超时. #include<iostream> #include&l ...

  6. webpack之loader和plugin简介

    webpack之loader和plugin简介 webpack入门和实战(二):全面理解和运用loader和plugins webpack入门(四)——webpack loader 和plugin w ...

  7. 网工的Linux系统学习历程

    偶遇篇作为一名通过思科CCNP认证的网络工程师,专注于网络技术.但在日常的工作中,难免不接触到服务器,对于大多数服务器来说,鉴于稳定性等因素的考虑,基本使用的都是Linux系统,包括RHEL.Cent ...

  8. MySQL 主从同步遇到的问题及解决方案

    在做某个项目的时候,使用主从数据库,master负责update.delete.insert操作,而slave负责select操作. 情景1:发表文章与查看文章 可以认为这个项目是一个博客系统,这里就 ...

  9. 将iso镜像转换为docker镜像

    为什么不用官方的镜像? 不是不想使用,而是官方镜像提供的功能实在是太少了,不信的话,你pull一个ubuntu:latest的进行,你看有没有wget.curl.ssh这些功能,就连最简单的ifcon ...

  10. tomcat8.0部署启动

    http://tomcat.apache.org/download-80.cgi 打开命令行提示符窗口, 进入Tomcat安装目录, 进入bin目录下, 输入:service.bat install  ...