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

P2596 [ZJOI2006]书架

题目描述

小T有一个很大的书柜。这个书柜的构造有些独特,即书柜里的书是从上至下堆放成一列。她用1到n的正整数给每本书都编了号。

小T在看书的时候,每次取出一本书,看完后放回书柜然后再拿下一本。由于这些书太有吸引力了,所以她看完后常常会忘记原来是放在书柜的什么位置。不过小T的记忆力是非常好的,所以每次放书的时候至少能够将那本书放在拿出来时的位置附近,比如说她拿的时候这本书上面有X本书,那么放回去时这本书上面就只可能有X-1、X或X+1本书。

当然也有特殊情况,比如在看书的时候突然电话响了或者有朋友来访。这时候粗心的小T会随手把书放在书柜里所有书的最上面或者最下面,然后转身离开。

久而久之,小T的书柜里的书的顺序就会越来越乱,找到特定的编号的书就变得越来越困难。于是她想请你帮她编写一个图书管理程序,处理她看书时的一些操作,以及回答她的两个提问:(1)编号为X的书在书柜的什么位置;(2)从上到下第i本书的编号是多少。

输入输出格式

输入格式:

第一行有两个数n,m,分别表示书的个数以及命令的条数;第二行为n个正整数:第i个数表示初始时从上至下第i个位置放置的书的编号;第三行到m+2行,每行一条命令。命令有5种形式:

1. Top S——表示把编号为S的书放在最上面。

2. Bottom S——表示把编号为S的书放在最下面。

3. Insert S T——T∈{-1,0,1},若编号为S的书上面有X本书,则这条命令表示把这本书放回去后它的上面有X+T本书;

4. Ask S——询问编号为S的书的上面目前有多少本书。

5. Query S——询问从上面数起的第S本书的编号。

输出格式:

对于每一条Ask或Query语句你应该输出一行,一个数,代表询问的答案。

说明

100%的数据,n,m <= 80000


这是我做的第一道非板子的平衡树题目,写+调大概花了2个小时,稍稍有点困,先以时间压到1个小时为目标了。

很显然,这颗平衡树是一颗区间树,用来平衡的域是书的相对位置大小,我们用树的大小信息来查询某个点在书架的相对位置,而不去直接存储这个相对位置以比较,这应该是区间树的一个重要特点。

\(pos[i]\)维护编号为\(i\)的书对应哪个节点。

对于操作:
放在最上面/下面就先删掉然后加点
添加的话只有两个情况,就先把要添加的节点伸展到根,然后和它的前驱/后继交换即可
两个询问互为逆操作,有关排名的


#include <cstdio>
#include <iostream>
#define ls t[now].ch[0]
#define rs t[now].ch[1]
#define f t[now].par
#define s t[now].ch[typ]
using namespace std;
const int N=160010;
struct Splay
{int ch[2],par,siz,num;
}t[N];
int root,tot=0,n,m,x,a[N],pos[N];//编号为i的书对应的当前点的编号
string S;
int identity(int now)
{return t[f].ch[1]==now;
}
void connect(int fa,int now,int typ)
{f=fa;t[fa].ch[typ]=now;
}
void updata(int now)
{t[now].siz=t[ls].siz+t[rs].siz+1;
}
void rotate(int now)
{int p=f,typ=identity(now);connect(p,t[now].ch[typ^1],typ);connect(t[p].par,now,identity(p));connect(now,p,typ^1);updata(p),updata(now);
}
void splay(int now,int to)
{to=t[to].par;for(int typ;f!=to;rotate(now))if(t[f].par!=to)rotate(identity(now)==identity(f)?f:now);if(!to) root=now;
}
int New(int dat)
{t[++tot].num=dat;t[tot].siz=1;return tot;
}
void free(int now)
{t[now].num=0;t[now].siz=0;t[now].par=0;ls=0;rs=0;if(tot==now) tot--;
}
void find(int x)//当前排名为x的书的编号
{int now=root;while(t[ls].siz+1!=x)now=t[now].ch[t[ls].siz+1<x?x-=t[ls].siz+1,1:0];splay(now,root);printf("%d\n",t[now].num);
}
int get_max(int now,int typ)
{if(typ) t[now].siz++;return rs?get_max(rs,typ):now;
}
int get_min(int now,int typ)
{if(typ) t[now].siz++;return ls?get_min(ls,typ):now;
}
void extrack(int now)//删除编号为now的点
{splay(now,root);if(!ls){root=rs;connect(0,root,1);free(now);return;}int rt=get_max(ls,0);splay(rt,ls);connect(rt,rs,1);connect(0,rt,1);updata(rt);root=rt;free(now);
}
void rank(int now)
{splay(now,root);printf("%d\n",t[ls].siz);
}
void top(int now,int num)//节点编号和书的编号
{extrack(now);int fa=get_min(root,1);connect(fa,now=New(num),0);pos[num]=now;updata(now);
}
void bottom(int now,int num)
{extrack(now);int fa=get_max(root,1);connect(fa,now=New(num),1);pos[num]=now;updata(now);
}
void exchange(int to,int now)
{swap(pos[t[to].num],pos[t[now].num]);swap(t[to].num,t[now].num);
}
void insert(int now,int T)
{if(!T) return;splay(now,root);if(T==1) exchange(get_min(rs,0),now);else exchange(get_max(ls,0),now);
}
int build(int l,int r,int fa)
{if(l>r) return 0;int now=l+r>>1;t[now].par=fa;t[now].num=a[now];updata(now);if(l==r) return now;ls=build(l,now-1,now);rs=build(now+1,r,now);updata(now);return now;
}
/*void write(int now)
{if(!now) return;write(ls);printf("%d ",t[now].num);write(rs);
}*/
int main()
{scanf("%d%d",&n,&m);for(int i=1;i<=n;i++){scanf("%d",a+i);pos[a[i]]=i;}connect(0,root=build(1,n,0),1);tot=n;for(int i=1;i<=m;i++){cin>>S;scanf("%d",&x);if(S=="Top")top(pos[x],x);else if(S=="Bottom")bottom(pos[x],x);else if(S=="Insert"){int T;scanf("%d",&T);insert(pos[x],T);}else if(S=="Ask")rank(pos[x]);elsefind(x);//write(root);//printf("%d\n");}return 0;
}

2018.6.14

转载于:https://www.cnblogs.com/butterflydew/p/9182269.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/465712.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

当卷烟厂也那么卷后……

过年回家&#xff0c;跟几个同学一起吃饭&#xff0c;聊到当时班上读书厉害的一个同学。同学嘴巴瞪得很大&#xff0c;说了一句&#xff0c;他在烟厂企业上班&#xff0c;现在开的什么什么车&#xff0c;待遇好得不得了。中学时候&#xff0c;那个同学读书真的厉害&#xff0c;…

微博平台StatusNet研究(4):快速安装

StatusNet研究系列StatusNet研究&#xff08;1&#xff09;&#xff1a;介绍StatusNet研究&#xff08;2&#xff09;&#xff1a;基本安装StatusNet研究&#xff08;3&#xff09;&#xff1a;友好URL与OpenID支持StatusNet研究&#xff08;4&#xff09;&#xff1a;快速安装…

Python3 —— if/while/input

Python3 —— if/while/input 目录 Python3 —— if/while/input 1.条件测试 2.if语句 3.input()函数 4.while循环 5.break与continue 1.条件测试 等于 ! 不等于 < 小于 < 小于等于 > 大于 > 大于等于 and 与 or 或 not in 不在 2…

python 全栈开发,Day63(子查询,MySQl创建用户和授权,可视化工具Navicat的使用,pymysql模块的使用)...

昨日内容回顾 外键的变种三种关系&#xff1a;多对一&#xff1a;左表的多 对右表一 成立左边的一 对右表多 不成立foreign key(从表的id) refreences 主表的&#xff08;id&#xff09;多对多建立第三张表&#xff08;foreign key&#xff09;一对一foreign keyunique单表查询…

我偶尔会用到的调试方法 | Linux 内核

文章转自我朋友的公众号&#xff0c;以下为内容正文大家好&#xff0c;我是你们的工具人老吴。今天,和大家分享一下几个 Linux 内核的调试小技巧。当你遇到一个 bug&#xff0c;你调试了 1 年半载都解决不了&#xff0c;这其实一件好事。因为它会时刻提醒你平时写代码时要谨慎、…

好像博问不能回复了,看似是某个脚本错误阻止了提交。可有此事?

针对问题&#xff1a;http://space.cnblogs.com/question/12190/ 我有这样一段回答&#xff0c;但始终发不上去&#xff1a; 如果可以的话&#xff0c;使用接口&#xff0c;比如&#xff1a; interface INamed{ string Name{get;set;} } class MyGenaric<T> where T: INa…

gcc、arm-linux-gcc和arm-elf-gcc的关系?

一、GCC简介The GNU Compiler Collection&#xff0c;通常简称 GCC&#xff0c;是一套由 GNU 开发的编译器集&#xff0c;为什么是编辑器集而不是编译器呢&#xff1f;那是因为它不仅支持 C 语言编译&#xff0c;还支持 C&#xff0c; Ada&#xff0c;Objective C 等许多语言。…

Mybatis中trim的使用

trim标记是一个格式化的标记&#xff0c;可以完成set或者是where标记的功能&#xff0c;如下代码&#xff1a; 1、 select * from user <trim prefix"WHERE" prefixoverride"AND |OR"> <if test"name ! null and name.length()>0"&…

取消win2003关机提示的设置

在"开始"|“运行”中输入gpedit.msc&#xff0c;出现"组策略界面"。用鼠标左键双击“计算机配置”文件夹 | “管理模板”文件夹 | “系统”文件夹。在对应“系统”文件夹窗口中&#xff0c;选中“关闭事件跟踪程序”转载于:https://blog.51cto.com/lzy8212…

Linux应用编程之共享内存实例

1共享内存实例01主要内容 上一小节小哥跟大家介绍了一下共享内存的知识&#xff0c;今天主要是做一个实战的演示&#xff0c;从而更好的理解共享内存的原理和实际应用。02程序示例 1#include <stdlib.h>2#include <stdio.h>3#include <string.h>4#inclu…

洛谷P1279 字串距离 (动态规划)

题目描述 设有字符串X&#xff0c;我们称在X的头尾及中间插入任意多个空格后构成的新字符串为X的扩展串&#xff0c;如字符串X为”abcbcd”&#xff0c;则字符串“abcb□cd”&#xff0c;“□a□bcbcd□”和“abcb□cd□”都是X的扩展串&#xff0c;这里“□”代表空格字符。 如…

Python3——函数

Python3——函数 目录 Python3——函数 定义函数 实参和形参 返回值 将函数存储在模块中 定义函数 关键字def告知Python要定义一个函数。 最后一行是调用此函数&#xff0c;此函数不带参数和返回值。 实参和形参 函数参数可以有一个或者多个&#xff0c;可以是简单数据…

ASP.NET MVC 整合 Spring.net(1)- Controller进容器

我们都知道Asp.net MVC自有一套执行机制。通过分析MVC的MvcHandler关键代码ProcessRequest protectedinternalvirtualvoidProcessRequest(HttpContextBase httpContext) { AddVersionHeader(httpContext); //Get the controller typestringcontrollerNam…

再读王垠的《编程的智慧》,有怎样的感想?

王垠老师的《编程的智慧》这篇文章已经读了最起码5遍了&#xff0c;最近的项目做完一个阶段&#xff0c;到了把他做干净的时候&#xff0c;也就是优化代码&#xff0c;全面整理的阶段&#xff0c;这个时候我又想起了这篇编程的智慧&#xff0c;有一些启发与大家分享。王垠老师的…

简单的FreeBSD 的内核编译

简单的FreeBSD 的内核编译 删除并重新下载内核源码 删除自带的内核源码rm -rf /usr/src下载内核源码wget https://download.freebsd.org/ftp/releases/amd64/11.1-RELEASE/src.txz也可以使用国内的源地址下载wget http://ftp1.chinafreebsd.cn/pub/FreeBSD/releases/amd64/11.1…

国外流行的五款免费在线图片编辑器评测

也许当你在度假的时候&#xff0c;不喜欢携带着你的笔记本电脑&#xff0c;但你在度假的时候一定会拍照。现在&#xff0c;你可以打理这些照片&#xff0c;甚至还可以在“网络咖啡屋”中进行一些高级的图像编辑。一些基于网络的照片编辑程序在去年逐渐兴起&#xff0c;大多是基…

Python3——类

Python3 —— 类 目录 Python3 —— 类 创建和使用类&#xff08;class&#xff09; 继承&#xff08;class Man(People)&#xff09; 导入类&#xff08;与导入模块一样&#xff09; 创建和使用类&#xff08;class&#xff09; 类&#xff1a;属性&#xff0c;方法 比…

void 型指针的高阶用法,你掌握了吗?

[导读] 要比较灵活的使用C语言实现一些高层级的框架时&#xff0c;需要掌握一些进阶编程技巧&#xff0c;这篇来谈谈void指针的一些妙用。测试环境采用 IAR for ARM 8.40.1推荐一首中文歌曲<<后来>>&#xff0c;英文翻唱<<life>>来自瑞典歌手Sofia Kal…

对图片进行压缩,水印,伸缩变换,透明处理,格式转换操作

对图片进行压缩,水印,伸缩变换,透明处理,格式转换操作 1 /**2 * <html>3 * <body>4 * <P> Copyright 1994 JsonInternational</p>5 * <p> All rights reserved.</p>6 * <p> Created on 19941115</p>7 * <p> C…

电子美图更新36张!

电子美图更新36张&#xff0c;下面请欣赏&#xff01;如果喜欢&#xff0c;请帮忙点“赞”和"在看"哦&#xff01;推荐阅读&#xff1a;专辑|Linux文章汇总专辑|程序人生专辑|C语言我的知识小密圈关注公众号&#xff0c;后台回复「1024」获取学习资料网盘链接。欢迎点…