cogs 330. [NOI2003] 文本编辑器
★★★ 输入文件:editor2003.in 输出文件:editor2003.out 简单对比
时间限制:2 s 内存限制:128 MB
【问题描述】
很久很久以前,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 |
光标后移一个字符 |
比如从一个空的文本编辑器开始,依次执行操作INSERT(13, “Balanced□tree”),MOVE(2),DELETE(5),NEXT(),INSERT(7, “□editor”),MOVE(0),GET(15)后,会输出“Bad□editor□tree”,如下表所示:
|
操作 |
操作前的文本 |
操作后的结果 |
|
INSERT(13, "Balanced□tree") |
| (只有光标,文本为空) |
|Balanced□tree |
|
MOVE(2) |
|Balanced□tree |
Ba|lanced□tree |
|
DELETE(5) |
Ba|lanced□tree |
Ba|d□tree |
|
NEXT() |
Ba|d□tree |
Bad|□tree |
|
INSERT(7, "□editor") |
Bad|□tree |
Bad|□editor□tree |
|
MOVE(0) |
Bad|□editor□tree |
|Bad□editor□tree |
|
GET(15) |
|Bad□editor□tree |
输出“Bad□editor□tree” |
上表中,“|”表示光标,“□”表示空格。 你的任务是:
- 建立一个空的文本编辑器。
- 从输入文件中读入一些操作指令并执行。
- 对所有执行过的GET操作,将指定的内容写入输出文件。
【输入文件】
输入文件的第一行是指令条数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秒,因此建议在可以的情况下使用后者。
【输出文件】
输出文件的每行依次对应输入文件中每条GET指令的输出。
【样例输入】
15
Insert 26
abcdefghijklmnop
qrstuv wxy
Move 15
Delete 11
Move 5
Insert 1
^
Next
Insert 1
_
Next
Next
Insert 4
.\/.
Get 4
Prev
Insert 1
^
Move 0
Get 22
【样例输出】
.\/.
abcde^_^f.\/.ghijklmno
题解:
本题用splay来维护,我们先在splay中插入两个'*'表示在序列的开端和结尾各有一个'*'方便以后处理,pos记录当前光标所在位置,因为在序列开头加上了'*',所以pos=光标所在的位置+1。
对于插入操作,可以先把要插入的序列建成一棵splay,假设光标在第k个字符的后面,那么让第k-1个字符旋至根,第k个字符旋至根的右孩子,所要加入的区间就是根的右孩子的左边那一块,直接把刚建好的splay插入。
删除操作就是找到要删除区间的左端点,把它旋至根,找到要删除区间的右端点,把它旋至根的右孩子,要删除的区间就是根的右孩子的左边那一块,直接删除即可。
剩下的操作就是直接对pos的操作,很好理解。
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<queue>
#include<vector>
using namespace std;
typedef long long LL;
const int maxn=;
int root,tot,fa[maxn],lc[maxn],rc[maxn],siz[maxn];
int T,N,pos=;
char opt[],ch[maxn],key[maxn];
inline void update(int x){
siz[x]=siz[lc[x]]++siz[rc[x]];
}
inline void r_rotate(int x){
int y=fa[x];
lc[y]=rc[x];
if(rc[x]) fa[rc[x]]=y;
fa[x]=fa[y];
if(y==lc[fa[y]]) lc[fa[y]]=x;
else rc[fa[y]]=x;
fa[y]=x; rc[x]=y;
update(y); update(x);
}
inline void l_rotate(int x){
int y=fa[x];
rc[y]=lc[x];
if(lc[x]) fa[lc[x]]=y;
fa[x]=fa[y];
if(y==lc[fa[y]]) lc[fa[y]]=x;
else rc[fa[y]]=x;
fa[y]=x; lc[x]=y;
update(y); update(x);
}
inline void splay(int x,int s){
int p;
while(fa[x]!=s){
p=fa[x];
if(fa[p]==s){
if(x==lc[p]) r_rotate(x);
else l_rotate(x);
break;
}
else if(x==lc[p]){
if(p==lc[fa[p]]) r_rotate(x),r_rotate(x);
else r_rotate(x),l_rotate(x);
}
else if(x==rc[p]){
if(p==rc[fa[p]]) l_rotate(x),l_rotate(x);
else l_rotate(x),r_rotate(x);
}
}
if(s==) root=x;
}
inline int find(int x,int rank){
if(siz[lc[x]]+==rank) return x;
else if(siz[lc[x]]+>rank) return find(lc[x],rank);
else return find(rc[x],rank-siz[lc[x]]-);
}
inline void split(int l,int r){
int x=find(root,l-),y=find(root,r+);
splay(x,); splay(y,root);
}
inline void newnode(int &x,char ch,int fath){
x=++tot;
fa[x]=fath; key[x]=ch;
lc[x]=rc[x]=; siz[x]=;
}
inline void insert(int &x,int l,int r,int fath){
int mid=(l+r)>>;
newnode(x,ch[mid],fath);
if(l+<=mid) insert(lc[x],l,mid-,x);
if(mid+<=r) insert(rc[x],mid+,r,x);
update(x);
}
inline void Delete(){
split(pos+,pos+N);
fa[lc[rc[root]]]=; lc[rc[root]]=;
update(rc[root]); update(root);
}
inline void print(int x){
if(lc[x]) print(lc[x]);
printf("%c",key[x]);
if(rc[x]) print(rc[x]);
}
inline void Get(){
split(pos+,pos+N);
print(lc[rc[root]]);
}
int main(){
newnode(root,'*',); newnode(rc[root],'*',root); update(root);
scanf("%d",&T);
while(T--){
scanf("%s",opt);
switch(opt[]){
case'M':
scanf("%d",&N);
pos=N+;
break;
case'I':
scanf("%d",&N);
for(int i=;i<=N;i++){
ch[i]=getchar();
while(ch[i]<||ch[i]>) ch[i]=getchar();
}
split(pos+,pos);//分割光标和光标的下一位
insert(lc[rc[root]],,N,rc[root]);
update(rc[root]); update(root);
break;
case'D':
scanf("%d",&N);
Delete();
break;
case'G':
scanf("%d",&N);
Get(); printf("\n");
break;
case'P':
pos--; break;
case'N':
pos++; break;
}
}
return ;
}
cogs 330. [NOI2003] 文本编辑器的更多相关文章
- [NOI2003] 文本编辑器 (splay)
复制炸格式了,就不贴题面了 [NOI2003] 文本编辑器 Solution 对于光标的移动,我们只要记录一下现在在哪里就可以了 Insert操作:手动维护中序遍历结果,即每次取中点像线段树一样一样递 ...
- 洛谷 P4008 [NOI2003]文本编辑器 解题报告
P4008 [NOI2003]文本编辑器 题目描述 很久很久以前,\(DOS3.x\)的程序员们开始对 \(EDLIN\) 感到厌倦.于是,人们开始纷纷改用自己写的文本编辑器⋯⋯ 多年之后,出于偶然的 ...
- [NOI2003]文本编辑器 [Fhq Treap]
[NOI2003]文本编辑器 没啥好说的 就是个板子 #include <bits/stdc++.h> // #define int long long #define rep(a , b ...
- luogu P4008 [NOI2003]文本编辑器 splay 块状链表
LINK:文本编辑器 这个东西感觉块状链表写细节挺多 (块状链表本来就难写 解释一下块状链表的做法:其实是一个个数组块 然后利用链表给链接起来 每个块的大小为sqrt(n). 这样插入删除的时候直接暴 ...
- NOI2003 文本编辑器editor
1507: [NOI2003]Editor Time Limit: 5 Sec Memory Limit: 162 MBSubmit: 1908 Solved: 738[Submit][Statu ...
- NOI2003 文本编辑器
练手QAQ #include<iostream> #include<algorithm> #include<cstdio> #include<cstdlib& ...
- 题解 P4008 【[NOI2003]文本编辑器】
块状链表及其应用 思路楼上已经说的很清楚了 看代码注释 代码很丑 #include<cstdio> #include<cctype> #include<cstring&g ...
- P4008 [NOI2003]文本编辑器
思路 FHQ Treap的板子 用FHQ Treap维护中序遍历序列即可 然后数组开够! 代码 #include <cstdio> #include <cstring> #in ...
- 【洛谷 P4008】 [NOI2003]文本编辑器 (Splay)
题目链接 \(Splay\)先练到这吧(好像还有道毒瘤的维护数列诶,算了吧) 记录下光标的编号,维护就是\(Splay\)基操了. 另外数据有坑,数据是\(Windows\)下生成了,回车是'\n\r ...
随机推荐
- pandas绘图总结
转自:http://blog.csdn.net/genome_denovo/article/details/78322628 pandas绘图总结 pandas中的绘图函数(更加详细的绘图资料可参考p ...
- 场景服务只创建了 Service Difinition 和feature layer
环境:物理机 pro1.4:虚拟机 (server + datastore + portal + adaptor) 10.4.1 发布场景服务,正常情况应portal中查看,应包含四部分内容:Serv ...
- 网站优化不等于搜索引擎优化SEO
对于SEO相信搞网络营销的人基本上都知道这个名词,英文全称为search engine optimization,中文一般叫搜索引擎优化,也有的叫搜索引擎定位(Search Engine Positi ...
- 【aws】
云服务器EC2 动态调整云服务器ec2 cpu.内存大小: 在ec2实例上右键,Instance settings--> Change Instance Type 选择一个合适的type 云数据 ...
- 如何使用Soft-NMS实现目标检测并提升准确率
非极大值抑制(Non-Maximum suppression,NMS)是物体检测流程中重要的组成部分.它首先基于物体检测分数产生检测框,分数高的检测框M被选中,其他与被选中检测框又明显重叠的检测框被抑 ...
- mysql集群搭建,主主复制
1:mysql搭建远程连接 https://www.cnblogs.com/davidgu/p/3706663.html 2: 两台主机能够相互通信 ,使用ping C:\Users\lenovo&g ...
- python处理图片验证码
WebDriver中实现对特定的Web区域截图方法 import pytesseract from PIL import Image image=Image.open('new.jpg') vcode ...
- javascript利用jquery-1.7.1来判断是否是谷歌Chrome浏览器
<!DOCTYPE html> <html> <head> <meta http-equiv="Content-Type" con ...
- tfs使用流程
1.用邮箱注册个微软账号,如zhangsan@outlook.com等邮箱 2.管理员会添加此用户zhangsan@outlook.com 3.打开vs,team-tfs-connect to ser ...
- css+table
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/ ...