BZOJ 1269: [AHOI2006]文本编辑器editor (splay tree)
1269: [AHOI2006]文本编辑器editor
Time Limit: 10 Sec Memory Limit: 162 MBSubmit: 1213 Solved: 454
[Submit][Status]
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操作不会把光标移动到非法位置。 输入文件没有错误。
Source
1 /* *********************************************** 2 Author :kuangbin 3 Created Time :2013/8/26 22:47:15 4 File Name :F:\2013ACM练习\专题学习\splay_tree_2\文本编辑器editor.cpp 5 ************************************************ */ 6 7 #include <stdio.h> 8 #include <string.h> 9 #include <iostream> 10 #include <algorithm> 11 #include <vector> 12 #include <queue> 13 #include <set> 14 #include <map> 15 #include <string> 16 #include <math.h> 17 #include <stdlib.h> 18 #include <time.h> 19 using namespace std; 20 21 /* 22 * 对字符串进行插入、删除、反转、查询第k个字符等操作 23 * Move k : 将光标移到到第k个字符之后 24 * Insert n S : 在光标后插入长度为n的字符串S,光标位置不变 25 * Delete n :删除光标后的n个字符,光标位置保持不变 26 * Rotate n :反转光标后的n个字符,光标位置不变 27 * Get :输出光标后的一个字符 28 * Prev :光标前移一个字符 29 * Next :光标后移一个字符 30 * 31 * 32 *用一个变量记录光标位置,对于Move,Prev,Next 直接改变这个变量 33 * 34 */ 35 #define Key_value ch[ch[root][1]][0] 36 const int MAXN = 2*1024*1024+10; 37 int ch[MAXN][2],pre[MAXN],rev[MAXN],size[MAXN]; 38 int root,tot1; 39 char key[MAXN]; 40 int s[MAXN],tot2; 41 42 int pos;//光标位置 43 char str[MAXN];//需要插入的字符串 44 void NewNode(int &r,int father,char k) 45 { 46 if(tot2) r = s[tot2--]; 47 else r = ++tot1; 48 ch[r][0] = ch[r][1] = 0; 49 pre[r] = father; 50 rev[r] = 0; 51 key[r] = k; 52 size[r] = 1; 53 } 54 void Update_Rev(int r) 55 { 56 if(!r)return; 57 swap(ch[r][0],ch[r][1]); 58 rev[r] ^= 1; 59 } 60 void push_up(int r) 61 { 62 size[r] = size[ch[r][0]] + size[ch[r][1]] + 1; 63 } 64 void push_down(int r) 65 { 66 if(rev[r]) 67 { 68 Update_Rev(ch[r][0]); 69 Update_Rev(ch[r][1]); 70 rev[r] = 0; 71 } 72 } 73 void Build(int &x,int l,int r,int father) 74 { 75 if(l > r)return; 76 int mid = (l+r)/2; 77 NewNode(x,father,str[mid]); 78 Build(ch[x][0],l,mid-1,x); 79 Build(ch[x][1],mid+1,r,x); 80 push_up(x); 81 } 82 void Init() 83 { 84 pos = 0; 85 root = tot1 = tot2 = 0; 86 ch[root][0] = ch[root][1] = pre[root] = size[root] = rev[root] = 0; 87 NewNode(root,0,' '); 88 NewNode(ch[root][1],root,' '); 89 push_up(ch[root][1]); 90 push_up(root); 91 } 92 void Rotate(int x,int kind) 93 { 94 int y = pre[x]; 95 push_down(y); 96 push_down(x); 97 ch[y][!kind] = ch[x][kind]; 98 pre[ch[x][kind]] = y; 99 if(pre[y]) 100 ch[pre[y]][ch[pre[y]][1]==y] = x; 101 pre[x] = pre[y]; 102 ch[x][kind] = y; 103 pre[y] = x; 104 push_up(y); 105 } 106 void Splay(int r,int goal) 107 { 108 push_down(r); 109 while(pre[r] != goal) 110 { 111 if(pre[pre[r]] == goal) 112 { 113 push_down(pre[r]); 114 push_down(r); 115 Rotate(r,ch[pre[r]][0]==r); 116 } 117 else 118 { 119 push_down(pre[pre[r]]); 120 push_down(pre[r]); 121 push_down(r); 122 int y = pre[r]; 123 int kind = ch[pre[y]][0]==y; 124 if(ch[y][kind] == r) 125 { 126 Rotate(r,!kind); 127 Rotate(r,kind); 128 } 129 else 130 { 131 Rotate(y,kind); 132 Rotate(r,kind); 133 } 134 } 135 } 136 push_up(r); 137 if(goal == 0)root = r; 138 } 139 int Get_kth(int r,int k) 140 { 141 push_down(r); 142 int t = size[ch[r][0]] + 1; 143 if(t == k)return r; 144 if(t > k)return Get_kth(ch[r][0],k); 145 else return Get_kth(ch[r][1],k-t); 146 } 147 //在光标后插入长度为len的字符串 148 void INSERT(int len) 149 { 150 Splay(Get_kth(root,pos+1),0); 151 Splay(Get_kth(root,pos+2),root); 152 Build(Key_value,0,len-1,ch[root][1]); 153 push_up(ch[root][1]); 154 push_up(root); 155 } 156 void erase(int r) 157 { 158 if(r) 159 { 160 s[++tot2] = r; 161 erase(ch[r][0]); 162 erase(ch[r][1]); 163 } 164 } 165 void DELETE(int len) 166 { 167 Splay(Get_kth(root,pos+1),0); 168 Splay(Get_kth(root,pos+len+2),root); 169 erase(Key_value); 170 pre[Key_value] = 0; 171 Key_value = 0; 172 push_up(ch[root][1]); 173 push_up(root); 174 } 175 void Reverse(int len) 176 { 177 Splay(Get_kth(root,pos+1),0); 178 Splay(Get_kth(root,pos+len+2),root); 179 Update_Rev(Key_value); 180 push_up(ch[root][1]); 181 push_up(root); 182 } 183 184 int main() 185 { 186 //freopen("in.txt","r",stdin); 187 //freopen("out.txt","w",stdout); 188 int n; 189 int x; 190 char op[20]; 191 while(scanf("%d",&n) == 1) 192 { 193 Init(); 194 while(n--) 195 { 196 scanf("%s",&op); 197 if(op[0] == 'M') 198 { 199 scanf("%d",&x); 200 pos = x; 201 } 202 else if(op[0] == 'P')pos--; 203 else if(op[0] == 'N')pos++; 204 else if(op[0] == 'I') 205 { 206 scanf("%d%*c",&x); 207 gets(str); 208 INSERT(x); 209 } 210 else if(op[0] == 'D') 211 { 212 scanf("%d",&x); 213 DELETE(x); 214 } 215 else if(op[0] == 'R') 216 { 217 scanf("%d",&x); 218 Reverse(x); 219 } 220 else if(op[0] == 'G') 221 { 222 printf("%c\n",key[Get_kth(root,pos+2)]); 223 } 224 } 225 } 226 227 return 0; 228 }