首页 > 代码库 > 【BZOJ1269】[AHOI2006]文本编辑器editor Splay
【BZOJ1269】[AHOI2006]文本编辑器editor Splay
【BZOJ1269】[AHOI2006]文本编辑器editor
Description
这些日子,可可不和卡卡一起玩了,原来可可正废寝忘食的想做一个简单而高效的文本编辑器。你能帮助他吗?为了明确任务目标,可可对“文本编辑器”做了一个抽象的定义: 文本:由0个或多个字符构成的序列。这些字符的ASCII码在闭区间[32, 126]内,也就是说,这些字符均为可见字符或空格。光标:在一段文本中用于指示位置的标记,可以位于文本的第一个字符之前,文本的最后一个字符之后或文本的某两个相邻字符之间。文本编辑器:为一个可以对一段文本和该文本中的一个光标进行如下七条操作的程序。如果这段文本为空,我们就说这个文本编辑器是空的。 编写一个程序:? 建立一个空的文本编辑器。? 从输入文件中读入一些操作指令并执行。? 对所有执行过的GET操作,将指定的内容写入输出文件。
Input
输入文件中第一行是指令条数N,以下是需要执行的N个操作。除了回车符之外,输入文件的所有字符的ASCII码都在闭区间[32, 126]内。且行尾没有空格。
Output
依次对应输入文件中每条GET指令的输出,不得有任何多余的字符。
Sample Input
Insert 13
Balanced eert
Move 2
Delete 5
Next
Insert 7
editor
Move 0
Get
Move 11
Rotate 4
Get
Sample Output
t
HINT
对输入数据我们有如下假定:? MOVE操作不超过50 000个,INSERT、DELETE和ROTATE操作作的总个数不超过6 000,GET操作不超过20 000个,PREV和NEXT操作的总个数不超过20 000。? 所有INSERT插入的字符数之和不超过2M(1M=1 024*1 024)。? DELETE操作、ROTATE操作和GET操作执行时光标后必然有足够的字符。MOVE、PREV、NEXT操作不会把光标移动到非法位置。? 输入文件没有错误。
题解:依旧是Splay裸题,但是有一点很坑:
就是gets()在读入整行时会忽略前导的空格,于是我们必须在读入上一个变量时加一个scanf("%*c")或者getchar()来防止将空格省略掉,或者一个一个字符读进来
#include <cstdio> #include <cstring> #include <iostream> using namespace std; int n,m,root,now,tot; struct node { int ch[2],fa,v,siz,tag; }s[1024*2048+10]; char str[1024*2048+10]; void pushup(int x) { s[x].siz=s[s[x].ch[0]].siz+s[s[x].ch[1]].siz+1; } void pushdown(int x) { if(s[x].tag) { swap(s[x].ch[0],s[x].ch[1]); s[s[x].ch[0]].tag^=1,s[s[x].ch[1]].tag^=1; s[x].tag=0; } } int find(int y,int x) { if(!x) return 0; pushdown(x); if(s[s[x].ch[0]].siz>=y) return find(y,s[x].ch[0]); if(s[s[x].ch[0]].siz+1==y) return x; return find(y-s[s[x].ch[0]].siz-1,s[x].ch[1]); } void rotate(int x,int &k) { int y=s[x].fa,z=s[y].fa,d=(x==s[y].ch[1]); if(z) s[z].ch[(y==s[z].ch[1])]=x; if(y==k) k=x; s[x].fa=z,s[y].fa=x,s[y].ch[d]=s[x].ch[d^1]; if(s[x].ch[d^1]) s[s[x].ch[d^1]].fa=y; s[x].ch[d^1]=y; pushup(y),pushup(x); } void splay(int x,int &k) { while(x!=k) { int y=s[x].fa,z=s[y].fa; if(y!=k) { if((x==s[y].ch[0])^(y==s[z].ch[0])) rotate(x,k); else rotate(y,k); } rotate(x,k); } } void build(int l,int r,int last,int d) { if(l>r) return ; int tmp=++tot,mid=l+r>>1; s[tmp].fa=last; s[last].ch[d]=tmp; s[tmp].v=str[mid]-32; build(l,mid-1,tmp,0),build(mid+1,r,tmp,1); pushup(tmp); } int main() { scanf("%d",&n); s[1].ch[1]=2,s[1].siz=2,s[2].siz=1,s[2].fa=1,now=root=1,tot=2; for(int i=1;i<=n;i++) { scanf("%s",str); switch(str[0]) { case ‘M‘: { scanf("%d",&now),now++; break; } case ‘I‘: { scanf("%d%*c",&m); gets(str); splay(find(now,root),root),splay(find(now+1,root),s[root].ch[1]); build(0,m-1,s[root].ch[1],0); pushup(s[root].ch[1]),pushup(root); break; } case ‘D‘: { scanf("%d",&m); splay(find(now,root),root),splay(find(now+m+1,root),s[root].ch[1]); s[s[root].ch[1]].ch[0]=0; pushup(s[root].ch[1]),pushup(root); break; } case ‘R‘: { scanf("%d",&m); splay(find(now,root),root),splay(find(now+m+1,root),s[root].ch[1]); s[s[s[root].ch[1]].ch[0]].tag^=1; break; } case ‘G‘: { printf("%c\n",s[find(now+1,root)].v+32); break; } case ‘P‘: { now--; break; } case ‘N‘: { now++; break; } } } return 0; }
【BZOJ1269】[AHOI2006]文本编辑器editor Splay