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 ...
随机推荐
- docker jenkins 安装
1:官方教程 https://jenkins.io/zh/doc/book/installing/ 2:拉取jenkins镜像 docker pull jenkinsci/blueocean 3:输入 ...
- mysql 不能加载表问题
记录一次 mysql 5.7 下,出现重启数据库后不能加载特定表的问题处理. 搜索了很多的类似的错误,大多都是说因为外键同名的索引丢失的情况.但在5.7这个版本下,会禁止更新外键关联的索引. 最后经过 ...
- Mac-App Store 购买过程中出错 请求超时
打开终端 输入下面命令回车: defaults delete com.apple.appstore.commerce Storefront 接上步骤,继续输入下面命令回车: defaults writ ...
- 想在don‘t starve中活的更久?那饥荒海难攻略你怎么能不知道!
饥荒海难mac版是一款非常好玩的烧脑游戏.玩家将扮演一个勇敢的绅士科学家威尔逊,被一个恶魔困住并送到一个神秘的荒野世界,玩家必须利用异世界中的自然资源让自己存活下去,并且抵御各种异世界生物的威胁.想在 ...
- 基于云开发开发 Web 应用(二):界面 UI 开发
工作量分析 在我们进行这部分开发的时候,接下来我们需要进行相应的功能安排和分类. 简单看来,我需要开发 3 个页面: 首页:首页负责用户默认访问. 列表页:列表页面则是在搜索过程中,如果有多个结果,则 ...
- Umi 小白纪实(一)—— 创建项目&常用配置
umi 是一个企业级 react 应用框架,也是蚂蚁金服的底层前端框架 <蚂蚁金服的前端框架和工程化实践> 一.安装脚手架 在创建项目之前,需要保证有 node 8.10 以上的环境 可以 ...
- MySql -- check 约束
6.CHECK 约束:用于限制列中的值的范围 在一些情况下,我们需要字段在指定范围的输入,例如:性别只能输入 '男'或者'女',余额只能大于0等条件,我们除了在程序上控制以外,我们还能使用 CHECK ...
- opencv —— createTrackbar、getTrackbarPos 滑动条的创建和使用
创建滑动条:createTrackbar 函数 createTrackbar 函数用于创建一个可以调整数值的滑动条,并将滑动条附加在指定的窗口上. int createTrackbar(const s ...
- Anaconda 常用命令
目录 包管理 环境管理 共享环境设置 包管理 安装包 conda install xxx conda install pandas ; conda install pandas numpy ; 同时安 ...
- Java不同单词个数统计
描述 编写一个程序,输入一个句子,然后统计出这个句子当中不同的单词个数.例如:对于句子“one little two little three little boys”,总共有5个不同的单词:one, ...