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 ...
随机推荐
- 关于elementui的table组件单元格的内容自定义写法
------------恢复内容开始------------ 记录老哥的写法 columns是表格的配置文件 在表格渲染的时候通过renderTableCell传入表格的row以及配置文件中的rend ...
- 重构与动态为angularjs栏位赋值或获取值
先来看下面一段html: 这个ng-model名称带有一定的规律带有序号. 先来实现数据绑定,从数据取到数据后,为ng-model绑定相对应的值: var c = response.data $sco ...
- 【python数据挖掘】爬取豆瓣影评数据
概述: 爬取豆瓣影评数据步骤: 1.获取网页请求 2.解析获取的网页 3.提速数据 4.保存文件 源代码: # 1.导入需要的库 import urllib.request from bs4 impo ...
- [SDOI2012] 任务安排 题解
有感而发,遂书. 其实和sze聊了很久,但他还是退役了.恐怕他是本届里学oi时间最长的一个人吧,从小学五年级开始.我也是因为他,才开始学oi的.他因为学校的压力,不得不放弃.或许是没什么天赋.学了4年 ...
- LOJ6287 诗歌
题意 给定一个排列,问是否存在\(\forall a,b,a\neq b\)满足\(2|(a+b)\)且\(\frac{a+b}{2}\)在\(a,b\)间 做法 枚举中点\(a\),即需要存在类似\ ...
- C. Long Beautiful Integer
题目思路还是很直接,首先按要求生成字符串.如果该目标字符串小于原字符串,那么从第k位开始,找到最后一个非9的位置,++,同时如果有9,要考虑进位(一开始没有考虑WA了一次). 犯了一个错误,就是比较字 ...
- MySQL manager or server PID file could not be found!
[root@centos var]# service mysqld stop MySQL manager or server PID file could not be found! [F ...
- spring boot中通用应用程序属性
可以在application.properties文件内部application.yml,文件内部或命令行开关中指定各种属性.本附录提供了常见的Spring Boot属性列表以及对使用它们的基础类的引 ...
- python 学习笔记之手把手讲解如何使用原生的 urllib 发送网络请求
urllib.urlopen(url[,data[,proxies]]) : https://docs.python.org/2/library/urllib.html python 中默认自带的网络 ...
- 修改Ubuntu的apt-get源为国内镜像源的方法
1.原文件备份 sudo cp /etc/apt/sources.list /etc/apt/sources.list.bak 2.编辑源列表文件 sudo vim /etc/apt/sources. ...