洛谷 P2596 [ZJOI2006]书架 (splay)
题目描述
小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
题解:先依次将点插入splay,权值为x[i]的第i个插入,splay维护的是顺序
显然插入到第x+1本或者第x-1本书的操作是将x的权值与他的后继或者前驱交换
插到底或者顶就是将x的左子树换到他的后继的左子树或者将x的右子树换到他的前驱的右子树
然后就可以用splay瞎搞了
代码如下:
#include<set>
#include<map>
#include<cmath>
#include<queue>
#include<stack>
#include<vector>
#include<cstdio>
#include<string>
#include<cstring>
#include<iostream>
#include<algorithm>
#define lson ch[x][0]
#define rson ch[x][1]
#define mod 1000000007
using namespace std; int n,m;
int pos[],sz[],key[],f[],ch[][],cnt,rt; int push_up(int x)
{
sz[x]=sz[lson]+sz[rson]+;
pos[key[lson]]=lson;
pos[key[rson]]=rson;
} int rotate(int x)
{
int y=f[x],z=f[y],kd=(ch[y][]==x),xs=ch[x][!kd];
if(z) ch[z][ch[z][]==y]=x;
ch[x][!kd]=y;
ch[y][kd]=xs;
if(xs) f[xs]=y;
f[x]=z;
f[y]=x;
push_up(y);
} int splay(int goal,int x)
{
int y,z;
while(f[x]!=goal)
{
y=f[x],z=f[y];
if(z!=goal)
{
(ch[y][]==x)^(ch[z][]==y)?rotate(x):rotate(y);
}
rotate(x);
}
push_up(x);
if(!goal) rt=x;
} int insert(int x)
{
key[++cnt]=x;
sz[cnt]=;
pos[x]=cnt;
ch[cnt][]=ch[cnt][]=;
if(cnt>)
{
ch[cnt-][]=cnt;
f[cnt]=cnt-;
splay(,cnt);
}
} int find(int x,int tot)
{
if(sz[lson]+==tot)
{
return x;
}
else
{
if(sz[lson]+<tot)
{
return find(rson,tot-sz[lson]-);
}
else return find(lson,tot);
}
} int get(int x,int kd)
{
int y=ch[x][kd];
while(ch[y][!kd])
{
y=ch[y][!kd];
}
return y;
} int make_top(int x)
{
x=pos[x];
splay(,x);
if(!lson) return ;
if(!rson) swap(lson,rson);
else
{
int y=get(x,);
f[lson]=y;
ch[y][]=lson;
lson=;
splay(,ch[y][]);
}
} int make_buttom(int x)
{
x=pos[x];
splay(,x);
if(!rson) return ;
if(!lson) swap(lson,rson);
else
{
int y=get(x,);
f[rson]=y;
ch[y][]=rson;
rson=;
splay(,ch[y][]);
}
} int change(int x,int kd)
{
if(!kd) return ;
splay(,pos[x]);
int y=(kd==)?get(pos[x],):get(pos[x],);
int tmp1=key[y],tmp2=pos[x];
swap(pos[x],pos[tmp1]);
swap(key[tmp2],key[y]);
} void print(int x)
{
splay(,x);
printf("%d\n",sz[lson]);
} void dayin(int x)
{
printf("%d %d %d\n",x,lson,rson);
if(lson) dayin(lson);
if(rson) dayin(rson);
} int main()
{
ch[][]=ch[][]=sz[]=f[]=key[]=pos[]=;
scanf("%d%d",&n,&m);
int tmp;
for(int i=; i<=n; i++)
{
scanf("%d",&tmp);
insert(tmp);
}
string op;
while(m--)
{
cin>>op;
int tmp1,tmp2;
if(op[]=='T')
{
scanf("%d",&tmp1);
make_top(tmp1);
}
if(op[]=='B')
{
scanf("%d",&tmp2);
make_buttom(tmp2);
}
if(op[]=='I')
{
scanf("%d%d",&tmp1,&tmp2);
change(tmp1,tmp2);
}
if(op[]=='A')
{
scanf("%d",&tmp1);
print(pos[tmp1]);
}
if(op[]=='Q')
{
scanf("%d",&tmp1);
printf("%d\n",key[find(rt,tmp1)]);
}
}
}
洛谷 P2596 [ZJOI2006]书架 (splay)的更多相关文章
- 洛谷 P2596 [ZJOI2006]书架 解题报告
P2596 [ZJOI2006]书架 题目描述 小T有一个很大的书柜.这个书柜的构造有些独特,即书柜里的书是从上至下堆放成一列.她用1到n的正整数给每本书都编了号. 小T在看书的时候,每次取出一本书, ...
- [洛谷P2596] [ZJOI2006]书架
洛谷题目链接:书架 题目描述 小T有一个很大的书柜.这个书柜的构造有些独特,即书柜里的书是从上至下堆放成一列.她用1到n的正整数给每本书都编了号. 小T在看书的时候,每次取出一本书,看完后放回书柜然后 ...
- 洛谷.2596.[ZJOI2006]书架(Splay)
题目链接 /* 五个操作: 1.将某元素置顶.删掉这个数,插入最左 2.将某元素置底.同样 3.旋到根后,直接将这个数与前驱/后继交换所有信息 不是左右子节点! 4.5.裸平衡树 ps:1.用pos[ ...
- P2596 [ZJOI2006]书架 && Splay 区间操作(三)
P2596 [ZJOI2006]书架 题目描述 小T有一个很大的书柜.这个书柜的构造有些独特,即书柜里的书是从上至下堆放成一列.她用1到n的正整数给每本书都编了号. 小T在看书的时候,每次取出一本书, ...
- fhq_treap || BZOJ1861: [Zjoi2006]Book 书架 || Luogu P2596 [ZJOI2006]书架
题面:P2596 [ZJOI2006]书架 题解:记录每本书对应的节点编号 普通fhq_treap无法查询一个权值的排名,所以在普通fhq_treap上多记录每个节点的父亲(可加在pushup函数中) ...
- BZOJ3224/洛谷P3391 - 普通平衡树(Splay)
BZOJ链接 洛谷链接 题意简述 模板题啦~ 代码 //普通平衡树(Splay) #include <cstdio> int const N=1e5+10; int rt,ndCnt; i ...
- [洛谷P3391] 文艺平衡树 (Splay模板)
初识splay 学splay有一段时间了,一直没写...... 本题是splay模板题,维护一个1~n的序列,支持区间翻转(比如1 2 3 4 5 6变成1 2 3 6 5 4),最后输出结果序列. ...
- [洛谷P2584][ZJOI2006]GameZ游戏排名系统
题目大意:同[洛谷P4291][HAOI2008]排名系统(双倍经验) 题解:略 卡点:无 C++ Code: #include <cstdio> #include <map> ...
- P2596 [ZJOI2006]书架(splay)
[题目链接] https://www.luogu.org/problemnew/show/P2596 平衡树,需支持五个操作: 1. 将某元素置顶:将元素旋到根,然后将左子树合并到该元素的后继 2. ...
随机推荐
- 流媒体协议部分RTP、RTCP、RTSP、MMS、HLS、HTTP progressive streaming
流媒体协议:(RTP.RTCP.RTSP.MMS.HLS.HTTP progressive streaming) 当前在internet上传送音频和视频等信息主要有两种方式: 下载,完整下载一个视频, ...
- 新浪微博Oauth2.0授权 获取Access Token
新浪微博开放平台提供了丰富的API接口,利用这些接口,开发者能够开发出独具特色的微博应用.但是,大部分接口都需要用户授权给应用,应用利用授权得到的Access Token来调用相应的接口来获取内容. ...
- SWFUpload初体验 For Struts1.x
SWFUpload是一个客户端文件上传工具,最初由Vinterwebb.se开发,它通过整合Flash与JavaScript技术为WEB开发者提供了一个具有丰富功能继而超越传统<input ty ...
- Python实践练习:电话号码和 E-mail 地址提取程序
题目: 假设你有一个无聊的任务,要在一篇长的网页或文章中,找出所有电话号码和邮件地址.如果手动翻页,可能需要查找很长时间.如果有一个程序,可以在剪贴板的文本中查找电话号码和 E-mail 地址,那你就 ...
- mongodb Java(八)
package com.mongodb.text; import java.net.UnknownHostException; import com.mongodb.DB; import com.mo ...
- 聊聊flutter的UI布局
UI布局多半是套路,熟悉套路的规则. Flutter的UI布局也有一套规则 center center可以让任何元素在屏幕中居中,既是水平居中又是垂直居中,如果想让元素从上而下排列要怎么办呢?那就得使 ...
- i++的原子性问题
一.什么是原子性 简单的可以理解为:操作是不可再分割的,比如: int i=0; 但是i++的操作是可以再分的,比如: i++ //分解后 i=i+i 上面的代码在多线程环境下取值是有问题的,比如: ...
- VNC Linux 远程桌面控制软件
简介: VNC (Virtual Network Computer)是虚拟网络计算机的缩写. VNC 是一款优秀的远程控制工具软件,VNC 是在基于 UNIX 和 Linux 操作系统的免费的开源软件 ...
- canvas的性能优化
canvas玩多了后,就会自动的要开始考虑性能问题了.怎么优化canvas的动画呢? [使用缓存] 使用缓存也就是用离屏canvas进行预渲染了,原理很简单,就是先绘制到一个离屏canvas中,然后再 ...
- 前端开发之JavaScript HTML DOM理论篇二
主要内容: 1.HTML DOM元素 2.HTML DOM事件 一.DOM元素 主要操作有添加.删除和替换HTML元素 1.创建新的HTML元素 (1)方法一: appendChild() 追加 如 ...