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的操作,很好理解。

  1 #include<iostream>
  2 #include<cstdio>
  3 #include<cstdlib>
  4 #include<cstring>
  5 #include<cmath>
  6 #include<algorithm>
  7 #include<queue>
  8 #include<vector>
  9 using namespace std;
 10 typedef long long LL;
 11 const int maxn=3000000;
 12 int root,tot,fa[maxn],lc[maxn],rc[maxn],siz[maxn];
 13 int T,N,pos=1;
 14 char opt[20],ch[maxn],key[maxn];
 15 inline void update(int x){
 16     siz[x]=siz[lc[x]]+1+siz[rc[x]];
 17 }
 18 inline void r_rotate(int x){
 19     int y=fa[x];
 20     lc[y]=rc[x];
 21     if(rc[x]) fa[rc[x]]=y;
 22     fa[x]=fa[y];
 23     if(y==lc[fa[y]]) lc[fa[y]]=x;
 24     else rc[fa[y]]=x;
 25     fa[y]=x; rc[x]=y;
 26     update(y); update(x);
 27 }
 28 inline void l_rotate(int x){
 29     int y=fa[x];
 30     rc[y]=lc[x];
 31     if(lc[x]) fa[lc[x]]=y;
 32     fa[x]=fa[y];
 33     if(y==lc[fa[y]]) lc[fa[y]]=x;
 34     else rc[fa[y]]=x;
 35     fa[y]=x; lc[x]=y;
 36     update(y); update(x);
 37 }
 38 inline void splay(int x,int s){
 39     int p;
 40     while(fa[x]!=s){
 41         p=fa[x];
 42         if(fa[p]==s){
 43             if(x==lc[p]) r_rotate(x);
 44             else l_rotate(x);
 45             break;
 46         }
 47         else if(x==lc[p]){
 48             if(p==lc[fa[p]]) r_rotate(x),r_rotate(x);
 49             else r_rotate(x),l_rotate(x);
 50         }
 51         else if(x==rc[p]){
 52             if(p==rc[fa[p]]) l_rotate(x),l_rotate(x);
 53             else l_rotate(x),r_rotate(x);
 54         }
 55     }
 56     if(s==0) root=x;
 57 }
 58 inline int find(int x,int rank){
 59     if(siz[lc[x]]+1==rank) return x;
 60     else if(siz[lc[x]]+1>rank) return find(lc[x],rank);
 61     else return find(rc[x],rank-siz[lc[x]]-1);
 62 }
 63 inline void split(int l,int r){
 64     int x=find(root,l-1),y=find(root,r+1);
 65     splay(x,0); splay(y,root);
 66 }
 67 inline void newnode(int &x,char ch,int fath){
 68     x=++tot;
 69     fa[x]=fath; key[x]=ch;
 70     lc[x]=rc[x]=0; siz[x]=1;
 71 }
 72 inline void insert(int &x,int l,int r,int fath){
 73     int mid=(l+r)>>1;
 74     newnode(x,ch[mid],fath);
 75     if(l+1<=mid) insert(lc[x],l,mid-1,x);
 76     if(mid+1<=r) insert(rc[x],mid+1,r,x);
 77     update(x);
 78 }
 79 inline void Delete(){
 80     split(pos+1,pos+N);
 81     fa[lc[rc[root]]]=0; lc[rc[root]]=0;
 82     update(rc[root]); update(root);
 83 }
 84 inline void print(int x){
 85     if(lc[x]) print(lc[x]);
 86     printf("%c",key[x]);
 87     if(rc[x]) print(rc[x]);
 88 }
 89 inline void Get(){
 90     split(pos+1,pos+N);
 91     print(lc[rc[root]]);
 92 }
 93 int main(){
 94     newnode(root,‘*‘,0); newnode(rc[root],‘*‘,root); update(root);
 95     scanf("%d",&T);
 96     while(T--){
 97         scanf("%s",opt);
 98         switch(opt[0]){
 99             case‘M‘:
100                 scanf("%d",&N);
101                 pos=N+1;
102                 break;
103             case‘I‘:
104                 scanf("%d",&N);
105                 for(int i=1;i<=N;i++){
106                     ch[i]=getchar();
107                     while(ch[i]<32||ch[i]>126) ch[i]=getchar();
108                 }
109                 split(pos+1,pos);//分割光标和光标的下一位
110                 insert(lc[rc[root]],1,N,rc[root]);
111                 update(rc[root]); update(root);
112                 break;
113             case‘D‘:
114                 scanf("%d",&N);
115                 Delete();
116                 break;
117             case‘G‘:
118                 scanf("%d",&N);
119                 Get(); printf("\n");
120                 break;
121             case‘P‘:
122                 pos--; break;
123             case‘N‘:
124                 pos++; break;
125         }
126     }
127     return 0;
128 }
 
时间: 2024-10-12 21:28:19

cogs 330. [NOI2003] 文本编辑器的相关文章

NOI2003 文本编辑器editor

1507: [NOI2003]Editor Time Limit: 5 Sec  Memory Limit: 162 MBSubmit: 1908  Solved: 738[Submit][Status] Description Input 输入文件editor.in的第一行是指令条数t,以下是需要执行的t个操作.其中: 为了使输入文件便于阅读,Insert操作的字符串中可能会插入一些回车符,请忽略掉它们(如果难以理解这句话,可以参考样例). 除了回车符之外,输入文件的所有字符的ASCII码都在

洛谷P4008 [NOI2003]文本编辑器【splay】

题目描述 很久很久以前,$DOS3.x$ 的程序员们开始对 $EDLIN$ 感到厌倦.于是,人们开始纷纷改用自己写的文本编辑器?? 多年之后,出于偶然的机会,小明找到了当时的一个编辑软件.进行了一些简单的测试后,小明惊奇地发现:那个软件每秒能够进行上万次编辑操作(当然,你不能手工进行这样的测试) !于是,小明废寝忘食地想做一个同样的东西出来.你能帮助他吗? 为了明确目标,小明对"文本编辑器"做了一个抽象的定义: 文本:由 0 个或多个 ASCII 码在闭区间[3232 , 126126

NOI2003 文本编辑器

练手QAQ #include<iostream> #include<algorithm> #include<cstdio> #include<cstdlib> #include<cstring> #include<string> using namespace std; void setIO(const string& a) { freopen((a+".in").c_str(), "r"

商城项目整理(四)JDBC+富文本编辑器实现商品增加,样式设置,和修改

UEditor富文本编辑器:http://ueditor.baidu.com/website/ 相应页面展示: 商品添加: 商品修改: 前台商品展示: 商品表建表语句: 1 create table TEST.GOODS_TABLE 2 ( 3 gid NUMBER not null, 4 gname VARCHAR2(90), 5 gdetails CLOB, 6 gpicture VARCHAR2(100), 7 gprice NUMBER, 8 gleixing NUMBER, 9 gpi

C# RichTextBox 制作文本编辑器

本文利用一个简单的小例子[文本编辑器],讲解RichTextBox的用法. Windows窗体中的RichTextBox控件用于显示,输入和操作格式化的文本,RichTextBox除了拥有TextBox控件的所有功能外,还可以显示字体,颜色,链接,从文件中读取和加载图像,以及查找指定的字符.RichTextBox控件通常用于提供类似字体处理程序(如Microsoft Word)的文本操作和显示功能.RichTextBox控件可以显示滚动条,且默认根据需要进行显示. 涉及知识点: Selectio

java文本编辑器5

1 package peng_jun; 2 3 import java.awt.*; 4 import java.awt.event.*; 5 6 import javax.swing.*; 7 8 import java.io.*; 9 10 import javax.swing.filechooser.*; 11 12 import java.awt.datatransfer.*; 13 14 public class Text4 extends JFrame { 15 public sta

java文本编辑器 版本4

1 package peng_jun; 2 3 import java.awt.*; 4 import java.awt.event.*; 5 6 import javax.swing.*; 7 8 import java.io.*; 9 10 import javax.swing.filechooser.*; 11 12 import java.awt.datatransfer.*; 13 14 public class Text3 extends JFrame { 15 public sta

qt_文本编辑器实现_附带详细注释和源码下载

源码下载:http://pan.baidu.com/s/1hs2lx68 程序效果截图如下: 代码如下: 1 //imgprocessor.h 2 #ifndef IMGPROCESSOR_H 3 #define IMGPROCESSOR_H 4 5 #include <QMainWindow> 6 #include <QApplication> 7 #include <QImage> 8 #include <QLabel> 9 #include <Q

AHOI2006文本编辑器editor

1269: [AHOI2006]文本编辑器editor Time Limit: 10 Sec  Memory Limit: 162 MBSubmit: 1885  Solved: 683[Submit][Status] Description 这些日子,可可不和卡卡一起玩了,原来可可正废寝忘食的想做一个简单而高效的文本编辑器.你能帮助他吗?为了明确任务目标,可可对“文本编辑器”做了一个抽象的定义:   文本:由0个或多个字符构成的序列.这些字符的ASCII码在闭区间[32, 126]内,也就是说