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 ...
随机推荐
- PyCharm专业版激活+破解到期时间2100年
PyCharm专业版激活+破解到期时间2100年 转载文章:https://blog.51cto.com/13696145/2464312?source=dra 到2020年5月激活码: N7UR85 ...
- nginx 修改上传文件的大小限制
nginx默认的上传文件大小是有限制的,一般为2MB,如果你要上传的文件超出了这个值,将可能上传失败.修改的地方有: 1. php.ini: upload_max_filesize = 8M 2. ...
- Lucene之索引库的维护:添加,删除,修改
索引添加 Field域属性分类 添加文档的时候,我们文档当中包含多个域,那么域的类型是我们自定义的,上个案例使用的TextField域,那么这个域他会自动分词,然后存储 我们要根据数据类型和数据的用途 ...
- uniapp后台api设计(微信user表)
MySQL 创建数据库: CREATE DATABASE [IF NOT EXISTS] <数据库名> [[DEFAULT] CHARACTER SET <字符集名>] [[ ...
- window10家庭版解决IIS中万维网服务的安全性中无Windows身份验证
首先在左下角输入cmd搜索->命令提示符->以管理员身份运行->然后复制下面一段命令: dism /online /norestart /add-package:%SystemRoo ...
- jQuery---$冲突的解决方案
$冲突的解决方案 遇到其他js文件也用$包装了函数.可以把jQuery放在后面,并释放下$的控制权,也可以换个字符替代原来的$,例如$$ 或者,jQuery //jQuery释放$的控制权 $$ = ...
- Ubuntu禁用root账号,开启Ubuntu密钥登录
新建普通用户 ## 新建普通用户 $ adduser ubuntu $ apt-get install sudo ## 将用户加入sudo组 $ usermod -a -G sudo ubuntu 为 ...
- 9款最好用的MySQL数据库客户端图形界面管理工具,第三款我用了10年
MySQL的管理维护工具非常多,除了系统自带的命令行管理工具之外,还有许多其他的图形化管理工具,这里我介绍几个经常使用的MySQL图形化管理工具,供大家参考. MySQL是一个非常流行的小型关系型数据 ...
- [USACO19FEB]Painting the Barn G
题意 \(n\)个矩阵\((0\le x_1,y_1,x_2,y_2\le 200)\),可交,可以再放最多两个矩阵(这两个矩阵彼此不交),使得恰好被覆盖\(k\)次的位置最大.\(n,k\le 10 ...
- 清北学堂—2020.1提高储备营—Day 2 morning(并查集、堆)
qbxt Day 2 morning --2020.1.18 济南 主讲:李佳实 目录一览 1.并查集 2.堆 总知识点:基础数据结构 一.并查集 1.描述:并查集是一类十分常用的数据类型,它有着十分 ...