AHOI2006 文本编辑器(BZOJ1269)
传送门:http://www.lydsy.com/JudgeOnline/problem.php?id=1269
1269: [AHOI2006]文本编辑器editor
Time Limit: 10 Sec Memory Limit: 162 MBDescription
这些日子,可可不和卡卡一起玩了,原来可可正废寝忘食的想做一个简单而高效的文本编辑器。你能帮助他吗?为了明确任务目标,可可对“文本编辑器”做了一个抽象的定义: 文本:由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操作不会把光标移动到非法位置。 输入文件没有错误。
Source
鸣谢seter重新制作数据
这题是道不错的平衡树题。。就是初始时建树有些麻烦,这题用链式建树会方便。
。。坑爹的是我没加读入优化交了TLE。。加了读入优化之后1368ms。。
Codes:
1 #include<set> 2 #include<cstdio> 3 #include<cstdlib> 4 #include<cstring> 5 #include<iostream> 6 #include<algorithm> 7 using namespace std; 8 const int N = 1024 * 1024 * 2 + 10; 9 #define fa(i) (T[i].p) 10 #define L(i) (T[i].s[0]) 11 #define R(i) (T[i].s[1]) 12 #define Key (L(R(root))) 13 #define Loc(i) (T[fa(i)].s[1]==i) 14 #define For(i,n) for(int i=1;i<=n;i++) 15 #define Rep(i,l,r) for(int i=l;i<=r;i++) 16 #define Sets(a,b,c) {if(a) T[a].s[c] = b; if(b) fa(b) = a;} 17 struct tnode{ 18 int s[2],p,size,rev; 19 char v; 20 }T[N]; 21 22 char op[10],str[N]; 23 int n,tot,len,root,cur; 24 25 void Update(int i){ 26 T[i].size = T[L(i)].size + T[R(i)].size + 1; 27 } 28 29 void Pushdown(int i){ 30 if(T[i].rev){ 31 if(L(i)) T[L(i)].rev ^= 1; 32 if(R(i)) T[R(i)].rev ^= 1; 33 swap(L(i),R(i)); 34 T[i].rev = 0; 35 } 36 } 37 38 void Build(int l,int r,int p,int &i){ 39 if(l>r) return; 40 T[i=++tot].p = p;T[i].size = 1;T[i].rev = 0; 41 int m = (l+r)>>1; 42 T[i].v = str[m]; 43 Build(l,m-1,i,L(i));Build(m+1,r,i,R(i)); 44 Update(i); 45 } 46 47 int Rank(int kth,int i){ 48 Pushdown(i); 49 if(T[L(i)].size + 1 == kth) return i; 50 else if(T[L(i)].size >= kth) return Rank(kth,L(i)); 51 else return Rank(kth - T[L(i)].size - 1 , R(i)); 52 } 53 54 void Rot(int x){ 55 int y = fa(x) , z = fa(y); 56 int lx = Loc(x) , ly = Loc(y); 57 Pushdown(y);Pushdown(x); 58 Sets(y,T[x].s[!lx],lx); 59 Sets(z,x,ly); 60 Sets(x,y,!lx); 61 Update(y); 62 } 63 64 void Splay(int i,int goal){ 65 while(fa(i)!=goal){ 66 if(fa(fa(i))!=goal) Rot(fa(i)); 67 Rot(i); 68 } 69 Update(i); 70 if(!goal) root = i; 71 } 72 73 int read(){ 74 int num = 0; char ch = getchar(); 75 while(ch>'9'||ch<'0') ch = getchar(); 76 while(ch>='0'&&ch<='9'){ 77 num = num * 10 + ch - '0'; 78 ch = getchar(); 79 } 80 return num; 81 } 82 83 int main(){ 84 n = read(); 85 T[root=++tot].p = 0;R(root)=++tot;T[R(root)].p = root; 86 Update(R(root));Update(root); 87 For(i,n){ 88 scanf("%s",&op); 89 if(op[0]=='I'){ 90 len = read(); 91 gets(str); 92 Splay(Rank(cur+1,root),0); 93 Splay(Rank(cur+2,root),root); 94 Build(0,len-1,R(root),Key); 95 Update(R(root));Update(root); 96 }else 97 if(op[0]=='M'){ 98 len = read();cur = len; 99 }else 100 if(op[0]=='D'){ 101 len = read(); 102 Splay(Rank(cur+1,root),0); 103 Splay(Rank(cur+len+2,root),root); 104 T[Key].p = 0;T[R(root)].s[0] = 0; 105 Update(R(root));Update(root); 106 }else 107 if(op[0]=='N') cur++;else 108 if(op[0]=='P') cur--;else 109 if(op[0]=='G'){ 110 Splay(Rank(cur+2,root),0); 111 printf("%c\n",T[root].v); 112 }else 113 if(op[0]=='R'){ 114 len = read(); 115 Splay(Rank(cur+1,root),0); 116 Splay(Rank(cur+len+2,root),root); 117 T[Key].rev ^= 1; 118 } 119 } 120 return 0; 121 }