[ZJOI2006]书架(权值splay)
Description
题目描述
小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语句你应该输出一行,一个数,代表询问的答案。
Solution
- top/bottom:把S节点移到根,再把根的左子树、右子树移为后继/前驱的左儿子/右儿子
- insert:把S节点移到根,再与前驱/后继交换信息
- ask:把S节点移到根,输出左子树的size
- query:BST中第S大的点对应的编号
Code
- #include <cstdio>
- #include <cstdlib>
- #include <algorithm>
- using namespace std;
- const int N=8e4+;
- struct node
- {
- int size,v,ch[],fa;
- void clear()
- {
- size=v=fa=ch[]=ch[]=;
- }
- }f[N];
- int id[N],n,m,rt,S,T;
- char c[];
- void push_up(int g)
- {
- f[g].size=f[f[g].ch[]].size+f[f[g].ch[]].size+;
- }
- int get(int x)
- {
- return x==f[f[x].fa].ch[];
- }
- void rotate(int x)
- {
- int y=f[x].fa,z=f[y].fa;
- int wh=get(x);
- f[f[x].ch[wh^]].fa=y;
- f[y].ch[wh]=f[x].ch[wh^];
- f[x].ch[wh^]=y;
- f[x].fa=z,f[y].fa=x;
- if(z) f[z].ch[y==f[z].ch[]]=x;
- push_up(y),push_up(x);
- }
- void splay(int x)
- {
- for(int fx=f[x].fa;fx=f[x].fa,fx;rotate(x))
- if(f[fx].fa) rotate(get(x)==get(fx)?fx:x);
- rt=x;
- }
- int build(int l,int r,int fa)
- {
- int x=(l+r)>>;
- f[x].fa=fa;
- if(l==r) return x;
- if(l<x) f[x].ch[]=build(l,x-,x);
- if(x<r) f[x].ch[]=build(x+,r,x);
- push_up(x);
- return x;
- }
- int pre()
- {
- int x=f[rt].ch[];
- while(f[x].ch[]) x=f[x].ch[];
- return x;
- }
- int nxt()
- {
- int x=f[rt].ch[];
- while(f[x].ch[]) x=f[x].ch[];
- return x;
- }
- void change(int x,int t)
- {
- splay(x);
- if(!f[x].ch[t]) return ;
- if(!f[x].ch[t^])
- {
- swap(f[x].ch[],f[x].ch[]);
- return;
- }
- int y=(t==)?pre():nxt(),z=f[x].ch[t];
- f[y].ch[t]=z,f[z].fa=y,f[x].ch[t]=;
- while(y) push_up(y),y=f[y].fa;
- }
- void insert(int x,int t)
- {
- if(t==) return ;
- splay(x);
- int y=(t==)?nxt():pre();
- swap(f[x].v,f[y].v);
- swap(id[f[x].v],id[f[y].v]);
- }
- int kth(int k)
- {
- int x=rt;
- while()
- {
- int lc=f[x].ch[],rc=f[x].ch[];
- if(f[lc].size+==k) return x;
- else if(f[lc].size>=k) x=lc;
- else k-=f[lc].size+,x=rc;
- }
- }
- int main()
- {
- scanf("%d%d",&n,&m);
- for(int i=;i<=n;i++)
- {
- scanf("%d",&f[i].v);
- id[f[i].v]=i,f[i].size=;
- }
- rt=build(,n,);
- /*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本书的编号。*/
- while(m--)
- {
- scanf("%s",c);
- scanf("%d",&S);
- if(c[]=='T') change(id[S],);
- else if(c[]=='B') change(id[S],);
- else if(c[]=='I')
- {
- scanf("%d",&T);
- insert(id[S],T);
- }
- else if(c[]=='A')
- {
- splay(id[S]);
- printf("%d\n",f[f[rt].ch[]].size);
- }
- else if(c[]=='Q') printf("%d\n",f[kth(S)].v);
- }
- return ;
- }
[ZJOI2006]书架(权值splay)的更多相关文章
- 【模板】普通平衡树(权值splay)
安利splay讲解: [洛谷日报第62期]Splay简易教程 [模板]普通平衡树(luogu) Description 题目描述 您需要写一种数据结构(可参考题目标题),来维护一些数,其中需要提供以下 ...
- 【权值分块】bzoj1861 [Zjoi2006]Book 书架
权值分块……rank3……没什么好说的. #include<cstdio> #include<cmath> #include<algorithm> using na ...
- P2596 [ZJOI2006]书架 && Splay 区间操作(三)
P2596 [ZJOI2006]书架 题目描述 小T有一个很大的书柜.这个书柜的构造有些独特,即书柜里的书是从上至下堆放成一列.她用1到n的正整数给每本书都编了号. 小T在看书的时候,每次取出一本书, ...
- 洛谷 P2596 [ZJOI2006]书架 (splay)
题目描述 小T有一个很大的书柜.这个书柜的构造有些独特,即书柜里的书是从上至下堆放成一列.她用1到n的正整数给每本书都编了号. 小T在看书的时候,每次取出一本书,看完后放回书柜然后再拿下一本.由于这些 ...
- fhq_treap || BZOJ1861: [Zjoi2006]Book 书架 || Luogu P2596 [ZJOI2006]书架
题面:P2596 [ZJOI2006]书架 题解:记录每本书对应的节点编号 普通fhq_treap无法查询一个权值的排名,所以在普通fhq_treap上多记录每个节点的父亲(可加在pushup函数中) ...
- 线段树(单标记+离散化+扫描线+双标记)+zkw线段树+权值线段树+主席树及一些例题
“队列进出图上的方向 线段树区间修改求出总量 可持久留下的迹象 我们 俯身欣赏” ----<膜你抄> 线段树很早就会写了,但一直没有总结,所以偶尔重写又会懵逼,所以还是要总结一下. ...
- 洛谷 P2596 [ZJOI2006]书架 解题报告
P2596 [ZJOI2006]书架 题目描述 小T有一个很大的书柜.这个书柜的构造有些独特,即书柜里的书是从上至下堆放成一列.她用1到n的正整数给每本书都编了号. 小T在看书的时候,每次取出一本书, ...
- luogu P2596 [ZJOI2006]书架
传送门 感觉要死在\(Splay\)里了 orz 这题用\(Splay\)维护这个序列,其中的第\(k\)大点代表这个序列的第\(k\)个数 第一个操作,先把那个数所在的点旋到根,然后把整个根的左子树 ...
- BZOJ_3224 Tyvj 1728 普通平衡树 【离散化+权值线段树】
一 题面 Tyvj 1728 普通平衡树 二 分析 比较明显是可以用平衡二叉搜索树(splay)做的. 用权值线段树做,前提就是要先离散化,因为权值线段树维护的值域信息. 板子. 三 AC代码 #in ...
随机推荐
- ubuntu-wine
sudo dpkg --add-architecture i386 sudo add-apt-repository ppa:wine/wine-buildssudo apt-get update su ...
- Vsual Studio 2010可用的sqlite驱动程序(实体数据模型使用)
背景 昨天一个旧的项目(.net framework 4 + EF4 +sqlite + edmx db first),数据库结构有变更,要更新实体edmx模型 先是到官网下载最新的驱动,结果不能更新 ...
- 对EntityViewInfo的理解
1,EntityViewInfo常常用作bos中接口参数,来做查询用,其中包含了FilterInfo(过滤).Selector(指定属性)以及Sorter(排序) SelectorItemColl ...
- Ambari+HDP+HDF离线安装包下载清单
Ambari 2.7.3 Repositories OS Format URL RedHat 7 CentOS 7 Oracle Linux 7 Base URL http://public-repo ...
- C# event 事件
事件第二篇:https://www.cnblogs.com/FavoriteMango/p/11731485.html 曾经面试碰到一道设计题: 现有一个人,一群鸟,人有一把手枪,当人开枪时,所有的鸟 ...
- 初始Redis与简单使用
初始Redis: redis是一个key-value存储系统.和Memcached类似,它支持存储的value类型相对更多,包括string(字符串).list(链表).set(集合).zset(so ...
- k8s集群———flannel网络
#master执行将内网通信地址写入etcd中,确保flannel能与etcd通信 #添加 /opt/etcd/bin/etcdctl --ca-file=/opt/etcd/ssl/ca.pem - ...
- 老板让阿粉学习 flink 中的 Watermark,现在他出教程了
1 前言 在时间 Time 那一篇中,介绍了三种时间概念 Event.Ingestin 和 Process, 其中还简单介绍了乱序 Event Time 事件和它的解决方案 Watermark 水位线 ...
- $Luogu2512/CH122/AcWing122$糖果传递 模拟
$Luogu$ $AcWing$ $Description$ 有$n$个小朋友坐成一圈,每人有$a_i$个糖果. 每人只能给左右两人传递糖果. 每人每次传递一个糖果代价为$1$. 求使所有人获得均等 ...
- 「算法竞赛进阶指南」0x01 最短Hamilton路径 解题报告
题目在这里啊题目在这里~ Hamilton路径:将所有点都遍历刚好一次的路径 思路: 数据范围比较小(1~20),所以我们可以考虑暴力中的枚举 数组f[i][j] i的二进制表示选取了哪些点 j表示 ...