bzoj1861
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语句你应该输出一行,一个数,代表询问的答案。
输入输出样例
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
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的更多相关文章
- [BZOJ1861][Zjoi2006]Book 书架
[BZOJ1861][Zjoi2006]Book 书架 试题描述 小T有一个很大的书柜.这个书柜的构造有些独特,即书柜里的书是从上至下堆放成一列.她用1到n的正整数给每本书都编了号. 小T在看书的时候 ...
- 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 ...
- [bzoj1861][Zjoi2006]Book 书架_非旋转Treap
Book 书架 bzoj-1861 Zjoi-2006 题目大意:给你一个序列,支持:将指定编号的元素抽出,放到序列顶(底):将指定编号元素左右篡位:查询指定编号元素位置:查询指定数量位置元素编号. ...
- BZOJ1861——book
就是给你一摞书,然后又询问第k大,编号为x的书是第几大,然后修改书的位置 splay模板题...然而我还是不会,,,又遇到lrj的书的坑了,rj的书里没有father,顿时弄得我ask不会搞了 注意合 ...
- BZOJ-1861 Book 书架 Splay
1861: [Zjoi2006]Book 书架 Time Limit: 4 Sec Memory Limit: 64 MB Submit: 1010 Solved: 588 [Submit][Stat ...
- BZOJ1861[ZJOI2006]Book书架
Description 小T有一个很大的书柜.这个书柜的构造有些独特,即书柜里的书是从上至下堆放成一列.她用1到n的正整数给每本书都编了号. 小T在看书的时候,每次取出一本书,看完后放回书柜然后再拿下 ...
- 【BZOJ1861】【splay】Book 书架
Description 小 T有一个很大的书柜.这个书柜的构造有些独特,即书柜里的书是从上至下堆放成一列.她用1到n的正整数给每本书都编了号. 小T在看书的时候,每次取出一本书,看完后放回书柜然后再拿 ...
- [BZOJ1861][ZJOI2006]书架
BZOJ Luogu Description 小T有一个很大的书柜.这个书柜的构造有些独特,即书柜里的书是从上至下堆放成一列.她用1到n的正整数给每本书都编了号. 小T在看书的时候,每次取出一本书,看 ...
- BZOJ1861[Zjoi2006]书架——非旋转treap
题目描述 小T有一个很大的书柜.这个书柜的构造有些独特,即书柜里的书是从上至下堆放成一列.她用1到n的正整数给每本书都编了号. 小T在看书的时候,每次取出一本书,看完后放回书柜然后再拿下一本.由于这些 ...
随机推荐
- C语言的结构和联合,以及PHP是怎么实现弱类型的
C语言的结构(struct):包含多个成员,可能有多种数据类型,并且需要分配几种类型占用空间之和的空间. 联合(union):支持多种类型,供使用者使用其中一种数据类型,当然是需要分配其中占用空间最大 ...
- Vue bus的使用(兄弟|非父子组件传值)-->可以使用一个空的Vue实例作为中央事件总线new Vue()
1.在main.js中注册全局的bus Vue.prototype.bus=new Vue(); 2.在组建中使用 子组建使用:this.bus.$emit('自定义事件名',data) metho ...
- HTML+CSS之盒子模型
一.元素分类 CSS中html的标签元素大体分为三种类型 1.块状元素 @特点: #每个块级元素都从新的一行开始,并且其后的元素也另起一行(一个块级元素独占一行) #元素的高度.宽度.行高以及顶和底边 ...
- JVM规范系列开篇:为什么要读JVM规范?
许多人知道类加载机制.JVM内存模型,但他们可能不知道什么是<Java虚拟机规范>.对于Java开发来说,<Java虚拟机规范>才是最为官方.准确的一个文档,了解这个规范可以让 ...
- 升级NGINX支持HTTP/2服务端推送
内容概览 NGINX从1.13.9版本开始支持HTTP/2服务端推送,上周找时间升级了下NGINX,在博客上试验新的特性. 升级工作主要包括: 升级NGINX 修改NGINX配置 修改wordpres ...
- linux-高并发与负载均衡-TCP-IP基础知识
ARP协议: ping baidu
- net core 小坑杂记之配置文件读取 02 (控制器里读)
上次更新博客的时候提到了如何在EF的上下文里读取配置,这次介绍一下在控制器里如何读取. 先说一种简单易懂的: 首先以键值对的形式在appsettings里添加一条配置信息,接着Startup里注入配置 ...
- RabbitMQ防止消息丢失
转载请注明出处 0.目录 RabbitMQ-从基础到实战(1)— Hello RabbitMQ RabbitMQ-从基础到实战(3)— 消息的交换 1.简介 RabbitMQ中,消息丢失可以简单的分为 ...
- 不能再忽视了!宝宝不肯吃粥的N个原因,你避免了几个?
辅食不懂怎么添加? 宝宝吃饭爱挑食? 营养均衡和多样化的辅食 在这里你都能找到 宝宝辅食微课堂 不能再忽视了!宝宝不肯吃粥的N个原因,你避免了几个? 2017-10-09 09:35 辅食不懂怎么添加 ...
- Linux下查看文件系统磁盘使用
[root@localhost ~]# df -h 可以查看所有文件系统的磁盘使用情况 du --max-depth=1 -h 可以查看当前目录下各子目录的磁盘使用情况 参考:http://www.2 ...