洛谷 P4008 [NOI2003]文本编辑器 解题报告
P4008 [NOI2003]文本编辑器
题目描述
很久很久以前,\(DOS3.x\)的程序员们开始对 \(EDLIN\) 感到厌倦。于是,人们开始纷纷改用自己写的文本编辑器⋯⋯
多年之后,出于偶然的机会,小明找到了当时的一个编辑软件。进行了一些简单的测试后,小明惊奇地发现:那个软件每秒能够进行上万次编辑操作(当然,你不能手工进行这样的测试) !于是,小明废寝忘食地想做一个同样的东西出来。你能帮助他吗?
为了明确目标,小明对“文本编辑器”做了一个抽象的定义:
文本:由 \(0\) 个或多个 ASCII 码在闭区间\([32,126]\)内的字符构成的序列。
光标:在一段文本中用于指示位置的标记,可以位于文本首部,文本尾部或文本的某两个字符之间。
文本编辑器:由一段文本和该文本中的一个光标组成的,支持如下操作的数据结构。如果这段文本为空,我们就说这个文本编辑器是空的。
| 操作名称 | 输入文件中的格式 | 功能 |
|---|---|---|
| \(MOVE(k)\) | Move k | 将光标移动到第k个字符之后,如果k=0,将光标移到文本开头 |
| \(INSERT(n,s)\) | Insert n s | 在光标处插入长度为n的字符串s,光标位置不变n≥1 |
| \(DELETE(n)\) | Delete n | 删除光标后的n个字符,光标位置不变,n ≥ 1 |
| \(GET(n)\) | Get n | 输出光标后的n个字符,光标位置不变,n ≥ 1 |
| \(PREV()\) | Prev | 光标前移一个字符 |
| \(NEXT()\) | Next | 光标后移一个字符 |
你的任务是:
建立一个空的文本编辑器。
从输入文件中读入一些操作并执行。
对所有执行过的 GET 操作,将指定的内容写入输出文件。
输入输出格式
输入格式:
输入文件 editor.in 的第一行是指令条数 t,以下是需要执行的 t 个操作。其中:
为了使输入文件便于阅读, Insert 操作的字符串中可能会插入一些回车符, 请忽略掉它们(如果难以理解这句话,可以参照样例) 。
除了回车符之外,输入文件的所有字符的 ASCII 码都在闭区间[32, 126]内。且
行尾没有空格。
这里我们有如下假定:
MOVE 操作不超过 50000 个, INSERT 和 DELETE 操作的总个数不超过 4000,
PREV 和 NEXT 操作的总个数不超过 200000。
所有 INSERT 插入的字符数之和不超过 2M(1M=1024*1024 字节) ,正确的输出文件长度不超过 3M 字节。
DELETE 操作和 GET 操作执行时光标后必然有足够的字符。 MOVE 、 PREV 、 NEXT
操作必然不会试图把光标移动到非法位置。
输入文件没有错误。
对 对 C++ 选手的提示:经测试,最大的测试数据使用 fstream 进行输入有可能会比使用进行输入有可能会比使用 stdio 慢约 1 秒。*
输出格式:
输出文件 editor.out 的每行依次对应输入文件中每条 Get 指令的输出。
话说第一次见着这题是要用块状链表来着,今天不知道为什么就拿平衡树水了过去
感觉还是比较卡时间的
所以我们对于插入删除以及输出最好做到\(O(logn+S)\),而不是\(O(lognS)\)
(这里我对插入偷懒了emm
\(n\)为当前树的大小,\(s\)为操作的字符串长度
Code:
#include <cstdio>
#include <cstdlib>
#include <cstring>
#define ls ch[now][0]
#define rs ch[now][1]
const int N=1e6+10;
int ch[N][2],typ[N],val[N],siz[N],tot,root,t,pos,cnt,len;
char opt[12];
void updata(int now){siz[now]=siz[ls]+siz[rs]+1;}
void split(int now,int k,int &x,int &y)
{
if(!now) {x=y=0;return;}
if(siz[ls]+1<=k)
x=now,split(rs,k-siz[ls]-1,rs,y);
else if(siz[ls]>=k)
y=now,split(ls,k,x,ls);
updata(now);
}
int Merge(int x,int y)
{
if(!x||!y) return x+y;
if(val[x]<val[y])
{
ch[x][1]=Merge(ch[x][1],y);
updata(x);
return x;
}
else
{
ch[y][0]=Merge(x,ch[y][0]);
updata(y);
return y;
}
}
int New(int asc)
{
val[++tot]=rand(),typ[tot]=asc,siz[tot]=1;
return tot;
}
void Insert(int asc)
{
int x,y;
split(root,pos,x,y);
root=Merge(x,Merge(New(asc),y));
++pos;
}
void extrack()
{
scanf("%d",&cnt);
int x,y,z;
split(root,pos,x,y);
split(y,cnt,z,y);
root=Merge(x,y);
}
void dfs(int now)
{
if(!now) return;
dfs(ls);
printf("%c",typ[now]);
dfs(rs);
}
void out()
{
scanf("%d",&cnt);
int x,y,z;
split(root,pos,x,y);
split(y,cnt,z,y);
dfs(z);printf("\n");
root=Merge(x,Merge(z,y));
}
int main()
{
scanf("%d",&t);
while(t--)
{
scanf("%s",opt);
if(opt[0]=='M') scanf("%d",&pos);
else if(opt[0]=='I')
{
scanf("%d",&len);
char c;int lpos=pos;
while(len--)
{
c=getchar();
while(c<32||c>126||c=='\n') c=getchar();
Insert(c);
}
pos=lpos;
}
else if(opt[0]=='D') extrack();
else if(opt[0]=='G') out();
else if(opt[0]=='P') --pos;
else ++pos;
}
return 0;
}
2018.9.3
洛谷 P4008 [NOI2003]文本编辑器 解题报告的更多相关文章
- 洛谷 P4008 [NOI2003]文本编辑器
先推广一下 求赞 我们考虑这样的一个问题 给你一个序列,要求你支持插入,删除,查询单点值 如果用数组,查询O(1),插入删除最坏O(n) 如果用链表,插入删除O(1),查询最坏O(n) 如果用平衡树- ...
- 洛谷_Cx的故事_解题报告_第四题70
1.并查集求最小生成树 Code: #include <stdio.h> #include <stdlib.h> struct node { long x,y,c; ...
- 洛谷 P2317 [HNOI2005]星际贸易 解题报告
P2317 [HNOI2005]星际贸易 题目描述 输入输出格式 输入格式: 输出格式: 如果可以找到这样的方案,那么输出文件output.txt中包含两个整数X和Y.X表示贸易额,Y表示净利润并且两 ...
- 洛谷 P3802 小魔女帕琪 解题报告
P3802 小魔女帕琪 题目背景 从前有一个聪明的小魔女帕琪,兴趣是狩猎吸血鬼. 帕琪能熟练使用七种属性(金.木.水.火.土.日.月)的魔法,除了能使用这么多种属性魔法外,她还能将两种以上属性组合,从 ...
- 洛谷 P2606 [ZJOI2010]排列计数 解题报告
P2606 [ZJOI2010]排列计数 题目描述 称一个\(1,2,...,N\)的排列\(P_1,P_2...,P_n\)是\(Magic\)的,当且仅当对所以的\(2<=i<=N\) ...
- 洛谷1303 A*B Problem 解题报告
洛谷1303 A*B Problem 本题地址:http://www.luogu.org/problem/show?pid=1303 题目描述 求两数的积. 输入输出格式 输入格式: 两个数 输出格式 ...
- luogu P4008 [NOI2003]文本编辑器 splay 块状链表
LINK:文本编辑器 这个东西感觉块状链表写细节挺多 (块状链表本来就难写 解释一下块状链表的做法:其实是一个个数组块 然后利用链表给链接起来 每个块的大小为sqrt(n). 这样插入删除的时候直接暴 ...
- 洛谷 P4408 逃学的小孩 解题报告
P4408 [NOI2003]逃学的小孩 题目描述 Chris家的电话铃响起了,里面传出了Chris的老师焦急的声音:"喂,是Chris的家长吗?你们的孩子又没来上课,不想参加考试了吗?&q ...
- 洛谷 P2292 [HNOI2004] L语言 解题报告
P2292 [HNOI2004] L语言 题目描述 标点符号的出现晚于文字的出现,所以以前的语言都是没有标点的.现在你要处理的就是一段没有标点的文章. 一段文章\(T\)是由若干小写字母构成.一个单词 ...
随机推荐
- 搞定 mybatis generator 三步走
基于idea 编辑器下maven项目使用mybatis generator快速生成持久层 添加插件:插件网址:http://www.mybatis.org/generator/running/runn ...
- macOs 使用Homebrew升级到MySQL 8系列之后,php无法连接解决方法
当前时间2018-9-28 在使用brew install mysql 默认安装为 MySQL 8,但是使用php连接到数据库之后,出现了这种错误 (Unexpected server respose ...
- Codeforces Round #481 (Div. 3) 全题解
A题,题目链接:http://codeforces.com/contest/978/problem/A 解题心得:题意就是让你将这个数列去重,重复的数只保留最右边的那个,最后按顺序打印数列.set+m ...
- filter() 函数的使用
Python3 filter() 函数 描述 filter() 函数用于过滤序列,过滤掉不符合条件的元素,返回一个迭代器对象,如果要转换为列表,可以使用 list() 来转换. 该接收两个参数,第一个 ...
- 移动端的拖拽排序在react中实现 了解一下
最近做一个拖拽排序的功能找了好几个有一个步骤简单,结合redux最好不过了,话不多说上代码 第一步: npm install react-draggable-tags --save 第二步 sort. ...
- TouTiao开源项目 分析笔记15 新闻详情之两种类型的实现
1.预览效果 1.1.首先看一下需要实现的效果. 第一种,文字类型新闻. 第二种,图片类型新闻. 1.2.在NewsArticleTextViewBinder中设置了点击事件 RxView.click ...
- C# Dictionary的遍历理解
C# Dictionary容器类的理解 本文章由cartzhang编写,转载请注明出处. 所有权利保留. 文章链接:http://blog.csdn.net/cartzhang/article/det ...
- HDFS写数据和读数据流程
HDFS数据存储 HDFS client上传数据到HDFS时,首先,在本地缓存数据,当数据达到一个block大小时.请求NameNode分配一个block. NameNode会把block所在的Dat ...
- centos使用--开机启动
centos6.8 1.利用 chkconfig 来配置启动级别 在CentOS或者RedHat其他系统下,如果是后面安装的服务,如httpd.mysqld.postfix等,安装后系统默认不会自动启 ...
- 不想停机?快使用Windows Server 2016滚动升级
[TechTarget中国原创] Windows Server环境中的关键任务工作量总是密集的.工作量会主要集中在Hyper-V部署集群.硬件故障转移集群或者外来集群的顶部.集群中常用的表格都是基于F ...