ZJOI2006 书架 lg2596
题面见https://www.luogu.org/problemnew/show/P2596
题面就是描述了一个书柜从上到下放着书,可以看作一个序列,每个数的序号为它在从上向下数第几本
一开始建树偷了个懒,就直接一个个insert
因为题目中都是以书的编号进行操作,所以记一个pos[ ]
操作一:把pos[x] splay到根,左儿子都是比它编号小的,那么就把左儿子挂到根的后面,根+1的前面,具体怎么找这个点看代码解释
操作二:同一理
操作三:实际上只更改了x和x的前驱或后继的值,和他们代表的值的位置,只修改这两个标记即可
操作四:把pos[x] splay到根,左儿子都是比它编号小的,那么答案就是st[ls].size
操作五:常规查询第k大
#include<bits/stdc++.h>
using namespace std;
inline int read(){
int w=,f=;
char ch=getchar();
while(ch<''||ch>''){
if(ch=='-') f=-;
ch=getchar();
}
while(ch>=''&&ch<=''){
w=(w<<)+(w<<)+ch-;
ch=getchar();
}
return w*f;
}
int n,m,cnt,tot,root,a[],pos[];
bool debug;
struct node{
int val,ch[],size,f;
}st[];
inline void push_up(int x){
int ls=st[x].ch[];int rs=st[x].ch[];
st[x].size=st[ls].size+st[rs].size+;
pos[st[ls].val]=ls;pos[st[rs].val]=rs;
}
inline bool identify(int p){
return st[st[p].f].ch[]==p;
}
inline void connect(int x,int fa,int son){
st[x].f=fa;st[fa].ch[son]=x;return;
}
inline void rotate(int x){
int y=st[x].f;int z=st[y].f;
int yson=identify(x);int zson=identify(y);
int b=st[x].ch[yson^];
connect(b,y,yson);connect(y,x,(yson^));connect(x,z,zson);
push_up(y);push_up(x);if(z)push_up(z);return;
}
inline void splay(int x,int goal){
while(st[x].f!=goal){
int y=st[x].f;int z=st[y].f;
int yson=identify(x);int zson=identify(y);
if(z!=goal){
if(yson==zson) rotate(y);
else rotate(x);
}
rotate(x);
}
if(!goal) root=x;
return;
}//这以上都是常规操作
inline void insert(int x){
cnt++;int now=cnt;st[now].size=;
st[now].val=x;pos[x]=now;st[now].ch[]=st[now].ch[]=;
if(cnt>){//只要当前节点不是根,都要将它和父亲连一下,并splay到根
st[now].f=now-;st[now-].ch[]=now;
splay(now,);
}
}//建树操作 inline void output(int x){
int ls=st[x].ch[];int rs=st[x].ch[];
if(ls) output(ls);
printf("%d ",st[x].val);
if(rs) output(rs);
return;
}//输出整颗区间树,debug用的 inline int find(int p,int rk){
int ls=st[p].ch[];int rs=st[p].ch[];
if(st[ls].size+==rk) return p;
if(st[ls].size>=rk) return find(ls,rk);
return find(rs,rk-st[ls].size-);
}//找树上排名 inline void Top(int x){
x=pos[x];splay(x,);
if(!st[x].ch[]) return;//如果没有左儿子就不用管了
if(!st[x].ch[]){//没有右儿子就把左儿子挂过去就完事了
st[x].ch[]=st[x].ch[];st[x].ch[]=;return;
}
int ls=st[x].ch[];
int y=find(root,st[ls].size+);//根的rank是st[ls].size+1,st[ls].size+2为根的后继
st[ls].f=y;st[y].ch[]=ls;//根的左子树应该挂在根的后继的左子树
st[x].ch[]=;splay(y,);//最后把更改的点splay到根
return;
}
inline void Bottom(int x){//操作同上,反向操作即可
x=pos[x];splay(x,);
if(!st[x].ch[]) return;
if(!st[x].ch[]){
st[x].ch[]=st[x].ch[];st[x].ch[]=;return;
}
int ls=st[x].ch[];int rs=st[x].ch[];
int y=find(root,st[ls].size);
st[rs].f=y;st[y].ch[]=rs;
st[x].ch[]=;splay(y,);
return;
} inline void change(int x,int y){//题目中的insert操作
x=pos[x];splay(x,);if(!y) return;//如果y==0,说明就不用修改
int ls=st[x].ch[];
if(y==-){//y==-1就找前驱
y=find(root,st[ls].size);
}
else y=find(root,st[ls].size+);//y==1就找后缀
swap(pos[st[x].val],pos[st[y].val]);//这要修改两个点的值和两个点值的所在位置
swap(st[x].val,st[y].val);return;
} inline void rnk(int x){//常规查排名操作
x=pos[x];splay(x,);
int ls=st[x].ch[];
printf("%d\n",st[ls].size);return;
} inline void kth(int x){//常规排名找点操作
x=find(root,x);
printf("%d\n",st[x].val);return;
} int main(){
n=read();m=read();int i,j,k;root=;
for(i=;i<=n;i++){
int x=read();insert(x);
}
//debug=true;
while(m--){
string s;cin>>s;int x,y;
if(s[]=='T'){
x=read();Top(x);
}
if(s[]=='B'){
x=read();Bottom(x);
}
if(s[]=='I'){
x=read();y=read();change(x,y);
}
if(s[]=='A'){
x=read();rnk(x);
}
if(s[]=='Q'){
x=read();kth(x);
}
if(debug){
cout<<"debuging";
output(root);
cout<<endl;
}
}
return ;
}
ZJOI2006 书架 lg2596的更多相关文章
- 「luogu2569」[ZJOI2006] 书架
「luogu2569」[ZJOI2006]书架 题目大意 给定一个长度为 \(n\) 序列,序列中第 \(i\) 个元素有编号 \(a_i(a_i \in \Z \cap [1,n])\),需要支持五 ...
- 洛谷 P2596 [ZJOI2006]书架 解题报告
P2596 [ZJOI2006]书架 题目描述 小T有一个很大的书柜.这个书柜的构造有些独特,即书柜里的书是从上至下堆放成一列.她用1到n的正整数给每本书都编了号. 小T在看书的时候,每次取出一本书, ...
- P2596 [ZJOI2006]书架 && Splay 区间操作(三)
P2596 [ZJOI2006]书架 题目描述 小T有一个很大的书柜.这个书柜的构造有些独特,即书柜里的书是从上至下堆放成一列.她用1到n的正整数给每本书都编了号. 小T在看书的时候,每次取出一本书, ...
- [Luogu 2596] ZJOI2006 书架
[Luogu 2596] ZJOI2006 书架 第一次指针写 FHQ_Treap(省选噩梦数据结构)AC 啦! 省选试机写它,紧张过度失败了. 省选 Day 1 考场写它,写挂了. 省选 Day 1 ...
- fhq_treap || BZOJ1861: [Zjoi2006]Book 书架 || Luogu P2596 [ZJOI2006]书架
题面:P2596 [ZJOI2006]书架 题解:记录每本书对应的节点编号 普通fhq_treap无法查询一个权值的排名,所以在普通fhq_treap上多记录每个节点的父亲(可加在pushup函数中) ...
- [ZJOI2006]书架(权值splay)
[ZJOI2006]书架(luogu) Description 题目描述 小T有一个很大的书柜.这个书柜的构造有些独特,即书柜里的书是从上至下堆放成一列.她用1到n的正整数给每本书都编了号. 小T在看 ...
- wikioi 1514 and ZJOI2006 书架
1514 书架 0人推荐 收藏 发题解 提交代码 报错 题目描述 输入描述 输出描述 样例输入 样例输出 提示 题目描述 Description 小 T有一个很大的书柜.这个书柜的构造有些独特,即书柜 ...
- [洛谷P2596] [ZJOI2006]书架
洛谷题目链接:书架 题目描述 小T有一个很大的书柜.这个书柜的构造有些独特,即书柜里的书是从上至下堆放成一列.她用1到n的正整数给每本书都编了号. 小T在看书的时候,每次取出一本书,看完后放回书柜然后 ...
- BZOJ1861:[ZJOI2006]书架
浅谈\(splay\):https://www.cnblogs.com/AKMer/p/9979592.html 浅谈\(fhq\)_\(treap\):https://www.cnblogs.com ...
随机推荐
- 微信小程序组件构建UI界面小练手 —— 表单登录注册微信小程序
通过微信小程序中丰富的表单组件来完成登录界面.手机快速注册界面.企业用户注册界面的微信小程序设计. 将会用到view视图容器组件.button按钮组件.image图片组件.input输入框组件.che ...
- 常见Linux命令学习
Linux命令学习 命令分类: 文件处理命令 权限管理命令 文件搜索命令 帮助命令 用户管理命令 压缩解压命令 网络命令 关机重启命令 1.文件处理命令 命令格式:命令 [-选项] [参数] 例:ls ...
- 如何在IDEA的maven项目中连接并使用MySQL8.0
首先看一下我的基本的开发环境: 操作系统:MacOS 10.13.5 编辑器:IDEA 2018.3 其他:MySQL8.0.15.Maven 3.3.9.JDK 1.8 好,下面就正式开始: 第一步 ...
- 关于HashMap中的扰动函数的疑问
最近再看jdk8的hashmap源码,当看到这一步的时候有点疑问,去网上搜了一下,看到的所有文章基本上都是一篇抄一篇的(反正目前各大社区就是这么个状况),那个意思就是让高16位也参与运算,增加结果的随 ...
- c#中用office组件读取excel时提示异常来自 HRESULT:0x80010105 (RPC_E_SERVERFAULT)
在excel2007,找到“excel选项”,点开后点击“加载项”,最下面有个管理加载项的下拉菜单,选“COM加载项”,点“转到”,这时会弹出一个框,把里面pdf软件的加载项前面的勾去掉,点确定就ok ...
- Python 类 初学者笔记
面对象编程:编写表现世界中的事物和景象的类,并基于这些类创建对象,被创建的对象称为实例化. 创建类 class Dog(): #Python中类名称中的首字母要大写 def __init__(self ...
- 通过vsphere给esxi添加本地硬盘
公司ESXi服务器的硬盘空间不够使用,现在新加了一块硬盘在ESxi服务器上.在服务器上添加完硬盘后,在Vsphere上是看不到新加硬盘的. 下面我们来通过虚拟机模拟该情况,先添加一块硬盘.如下图: 在 ...
- JN_0017:在当前目录运行CMD
运行npm的时候,每次都要cd到目录,很麻烦,所以总结了三种在当前目录下直接打开cmd窗口的方法,供以后开发时参考,相信对其他人也有用. 方法一 在当前目录按住shift再右键. 会看到右键菜单里有一 ...
- [PAT] A1019 General Palindromic Number
[题目] https://pintia.cn/problem-sets/994805342720868352/problems/994805487143337984 题目大意:给定一个N和b,求N在b ...
- [Java]对double变量进行四舍五入,并保留小数点后位数
1.功能 将double类型变量进行四舍五入,并保留小数点后位数 2.代码 import java.math.BigDecimal; import java.math.RoundingMode; im ...