懒得复制,戳我戳我

Solution:

  • 还是一个\(Splay\),我们只用多存一个值\(rad\)来维护二叉树,然后用数组存下每个书对应的值是多少
  • \(Top\)操作,我是把\(s\)旋转到根节点,然后删除,将\(s\)对应的\(rad\)值调至最小,然后插入就可以
  • \(Bottom\)操作,就是和\(Top\)相反,删除后把\(rad\)调整至最大,然后插入
  • \(Insert\)操作,\(s==0\)不用操作,\(-1\)时,就只用把\(s\)旋转到根节点,把左子树最大值旋转至左子树根节点,然后交换两个节点信息,并且交换数组储存的每个书对应的\(rad\),\(1\)就是相反的旋转右子树最小值就可以
  • \(Ask\)操作,就只用把\(s\)旋转到根节点,输出左子树大小
  • \(Query\)操作,就是找第\(s\)大的\(rad\)值对应的书籍编号就可以了
  • 一开始想怎么找编号好久,发现编号是\(1-n\)就好操作了

Code:

//It is coded by Ning_Mew on 4.12
#include<bits/stdc++.h>
#define ls(x) node[x].ch[0]
#define rs(x) node[x].ch[1]
#define fa(x) node[x].fa
#define root node[0].ch[1]
using namespace std; const int maxn=8e4+10,INF=1e9+7; int n,m,tot,vall[maxn],low=0,up=0;
struct Node{
int fa,ch[2],val,num,size;//num-> bian hao val->rand()
}node[maxn]; void update(int x){node[x].size=node[ls(x)].size+node[rs(x)].size+1;}
void connect(int x,int fa,int how){node[x].fa=fa;node[fa].ch[how]=x;}
int ident(int x){return x==node[fa(x)].ch[0]?0:1;}
void rorate(int x){
int Y=fa(x),R=fa(Y);int Yson=ident(x),Rson=ident(Y);
connect(node[x].ch[Yson^1],Y,Yson);
connect(Y,x,Yson^1);
connect(x,R,Rson);
update(Y);update(x);
}
void Splay(int x,int goal){
int to=fa(goal);
while(fa(x)!=to){
if(fa(fa(x))==to)rorate(x);
else if(ident(x)==ident(fa(x)))rorate(fa(x)),rorate(x);
else rorate(x),rorate(x);
}
}
int newnode(int x,int rad,int fa){node[++tot].val=rad;node[tot].num=x;node[tot].size=1;node[tot].fa=fa;return tot;}
void ins(int x,int rad){
//cout<<x<<' '<<rad<<endl;
int now=root;
if(!root){newnode(x,rad,0);root=tot;return;}
else{
while(1){
node[now].size++;
int nxt=rad<node[now].val?0:1;
if(!node[now].ch[nxt]){
int p=newnode(x,rad,now);
node[now].ch[nxt]=p;Splay(p,root);return;
}
now=node[now].ch[nxt];
}
}return;
}
int find(int x,int rad){
int now=root;
while(1){
if(!now)return 0;
if(node[now].val==rad){Splay(now,root);return now;}
int nxt=rad<node[now].val?0:1;
now=node[now].ch[nxt];
}
}
void del(int x,int rad,int opt,int sum){//1->del 2->swap
int pos=find(x,rad);
if(!pos)return;
if(opt==1){
if(!ls(pos)&&!rs(pos)){root=0;return;}
if(!ls(pos)){root=rs(pos);fa(root)=0;return;}
else{
int left=ls(pos);
while(rs(left))left=rs(left);
Splay(left,ls(pos));
connect(rs(pos),left,1);
connect(left,0,1);update(left);
}
}else{
if(sum==0)return;
if(sum==-1&&!ls(pos))return;
if(sum==1&&!rs(pos))return;
if(sum==-1){
int left=ls(pos);
while(rs(left))left=rs(left);
Splay(left,ls(pos));
swap(vall[ node[pos].num ],vall[ node[left].num ]);
swap(node[pos].num,node[left].num);
}else{
int right=rs(pos);
while(ls(right))right=ls(right);
Splay(right,rs(pos));
swap(vall[ node[pos].num ],vall[ node[right].num ]);
swap(node[pos].num,node[right].num);
}
}
}
int rak(int x,int rad){int pos=find(x,rad);return node[ls(pos)].size;}
int kth(int x,int rad){
int now=root;
while(1){
if(x-node[ls(now)].size==1){
Splay(now,root);return node[now].num;}
int nxt=x<=node[ls(now)].size?0:1;
if(nxt){x=x-(node[ls(now)].size+1);}
now=node[now].ch[nxt];
}
}
string s;
int main(){
scanf("%d%d",&n,&m);
int x,t;
for(int i=1;i<=n;i++){
scanf("%d",&x);
ins(x,++up);vall[x]=up;
}
//cout<<"ins finished"<<endl;
for(int i=1;i<=m;i++){
cin>>s;scanf("%d",&x);
if(s=="Top"){
del(x,vall[x],1,0);vall[x]=--low;
ins(x,vall[x]);
}
if(s=="Bottom"){
del(x,vall[x],1,0);vall[x]=++up;
ins(x,vall[x]);
}
if(s=="Insert"){
scanf("%d",&t); del(x,vall[x],2,t);
}
if(s=="Ask"){printf("%d\n",rak(x,vall[x]));}
if(s=="Query"){printf("%d\n",kth(x,vall[x]));}
}
return 0;
}

【题解】 [ZJOI2006]书架 (Splay)的更多相关文章

  1. P2596 [ZJOI2006]书架 && Splay 区间操作(三)

    P2596 [ZJOI2006]书架 题目描述 小T有一个很大的书柜.这个书柜的构造有些独特,即书柜里的书是从上至下堆放成一列.她用1到n的正整数给每本书都编了号. 小T在看书的时候,每次取出一本书, ...

  2. 洛谷 P2596 [ZJOI2006]书架 (splay)

    题目描述 小T有一个很大的书柜.这个书柜的构造有些独特,即书柜里的书是从上至下堆放成一列.她用1到n的正整数给每本书都编了号. 小T在看书的时候,每次取出一本书,看完后放回书柜然后再拿下一本.由于这些 ...

  3. 洛谷.2596.[ZJOI2006]书架(Splay)

    题目链接 /* 五个操作: 1.将某元素置顶.删掉这个数,插入最左 2.将某元素置底.同样 3.旋到根后,直接将这个数与前驱/后继交换所有信息 不是左右子节点! 4.5.裸平衡树 ps:1.用pos[ ...

  4. BZOJ1861:[ZJOI2006]书架(Splay)

    Description 小T有一个很大的书柜.这个书柜的构造有些独特,即书柜里的书是从上至下堆放成一列.她用1到n的正整数给每本书都编了号. 小T在看书的时候,每次取出一本书,看完后放回书柜然后再拿下 ...

  5. [ZJOI2006]书架(权值splay)

    [ZJOI2006]书架(luogu) Description 题目描述 小T有一个很大的书柜.这个书柜的构造有些独特,即书柜里的书是从上至下堆放成一列.她用1到n的正整数给每本书都编了号. 小T在看 ...

  6. 「luogu2569」[ZJOI2006] 书架

    「luogu2569」[ZJOI2006]书架 题目大意 给定一个长度为 \(n\) 序列,序列中第 \(i\) 个元素有编号 \(a_i(a_i \in \Z \cap [1,n])\),需要支持五 ...

  7. 洛谷 P2596 [ZJOI2006]书架 解题报告

    P2596 [ZJOI2006]书架 题目描述 小T有一个很大的书柜.这个书柜的构造有些独特,即书柜里的书是从上至下堆放成一列.她用1到n的正整数给每本书都编了号. 小T在看书的时候,每次取出一本书, ...

  8. fhq_treap || BZOJ1861: [Zjoi2006]Book 书架 || Luogu P2596 [ZJOI2006]书架

    题面:P2596 [ZJOI2006]书架 题解:记录每本书对应的节点编号 普通fhq_treap无法查询一个权值的排名,所以在普通fhq_treap上多记录每个节点的父亲(可加在pushup函数中) ...

  9. [Luogu 2596] ZJOI2006 书架

    [Luogu 2596] ZJOI2006 书架 第一次指针写 FHQ_Treap(省选噩梦数据结构)AC 啦! 省选试机写它,紧张过度失败了. 省选 Day 1 考场写它,写挂了. 省选 Day 1 ...

随机推荐

  1. SystemView SEGGER FreeRTOS 移植和使用

    /* 官方帮助英文翻译文档参考:https://blog.csdn.net/bjr2016/article/category/7275877. */ /* 移植文档参考:https://blog.cs ...

  2. SqlServer执行大的数据库脚本出错解决方法

    如果执行线上项目拷下来sqlserver的.sql的数据库脚本文件,如果文件较大时,那么就会报错内存不足之类的. 这时可以在命令提示符使用命令来执行脚本文件.切记,执行前先改一下数据库存放位置! 命令 ...

  3. C# Test Encryption and Decryption

    public MainWindow() { InitializeComponent(); Title = getUUID(); string s= httpGet("http://220.1 ...

  4. RESTful API设计概要

    一.简介 1. 什么是REST REST全称是Representational State Transfer,中文意思是表述(编者注:通常译为表征)性状态转移. 它首次出现在2000年Roy Fiel ...

  5. 网络对抗技术 2017-2018-2 20152515 Exp6 信息搜集与漏洞扫描

    1.实践目标 掌握信息搜集的最基础技能与常用工具的使用方法.包括: (1)各种搜索技巧的应用 (2)DNS IP注册信息的查询 (3)基本的扫描技术:主机发现.端口扫描.OS及服务版本探测.具体服务的 ...

  6. [Deep-Learning-with-Python]计算机视觉中的深度学习

    包括: 理解卷积神经网络 使用数据增强缓解过拟合 使用预训练卷积网络做特征提取 微调预训练网络模型 可视化卷积网络学习结果以及分类决策过程 介绍卷积神经网络,convnets,深度学习在计算机视觉方面 ...

  7. PHP7添加opcache.so模块

    启动php报错如下: # /usr/local/php7/sbin/php-fpm [-Apr- ::] NOTICE: PHP message: PHP Warning: PHP Startup: ...

  8. 【第十课】Tomcat入门

    目录 1.Tomcat介绍 2.Tomcat安装部署和配置 (1)tomcat下载和解压 (2)jdk环境变量配置 (3)设置tomcat以普通用户启动 (4)查看tomcat的配置 (5)tomca ...

  9. JVM技术周报第1期

    JVM技术周报 · 第1期 JVM技术每周分享整理了JVM技术交流群每周讨论的内容,由群内成员整理归纳而成.如果你有兴趣入群讨论,请关注「Java技术精选」公众号,通过右下角菜单「入群交流」加我好友, ...

  10. OD之绕过序列号验证(二)

    上次是修改程序的标题,大家应该感觉这只是一个起点而已,接下来我们可以尝试绕过序列号验证,这种技术应用在很多软件中,比如淘宝上要买什么的软件,商家都会发给`你一个用户名和密码,而且还有试用期什么的,这确 ...