1269: [AHOI2006]文本编辑器editor
Time Limit: 10 Sec Memory Limit: 162 MBSubmit: 4718 Solved: 1807
[Submit][Status][Discuss]
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
分析
纪念:我的第一颗splay树!!!
写的有点丑,splay恰好都支持这些功能,所以用的是splay。。
code
1 #include<cstdio> 2 #include<algorithm> 3 #include<cstring> 4 #include<iostream> 5 #include<cmath> 6 #include<map> 7 #include<queue> 8 9 using namespace std; 10 11 const int N = 2000100; 12 13 int ch[N][2],fa[N],data[N],tag[N],siz[N]; 14 int t[100100],st[100100],top; 15 int tn,Root; 16 17 inline int read() { 18 int x = 0,f = 1;char ch = getchar(); 19 for (; ch<‘0‘||ch>‘9‘; ch = getchar()) 20 if (ch==‘-‘) f = -1; 21 for (; ch>=‘0‘&&ch<=‘9‘; ch = getchar()) 22 x = x*10+ch-‘0‘; 23 return x * f; 24 } 25 inline int son(int x) { 26 return x==ch[fa[x]][1]; 27 } 28 inline void pushup(int x) { 29 siz[x] = siz[ch[x][0]] + siz[ch[x][1]] + 1; 30 } 31 inline void pushdown(int x) { 32 if (tag[x]) { 33 tag[ch[x][0]] ^= 1;tag[ch[x][1]] ^= 1; 34 swap(ch[x][0],ch[x][1]); 35 tag[x] ^= 1; 36 } 37 } 38 inline void rotate(int x) { 39 int y = fa[x],z = fa[y],b = son(x),c = son(y),a = ch[x][!b]; 40 if (z) ch[z][c] = x;else Root = x;fa[x] = z; 41 ch[x][!b] = y;fa[y] = x; 42 ch[y][b] = a;if (a) fa[a] = y; 43 pushup(y);pushup(x); 44 } 45 inline void splay(int x,int rt) { 46 /* top = 0;int p = x; 47 while (p) st[++top] = p,p = fa[p]; 48 while (top) pushdown(st[top]),top--;*/ // 这个地方在查找是已经下传了 49 while (fa[x] != rt) { 50 int y = fa[x],z = fa[y]; 51 if (z==rt) rotate(x); 52 else { 53 if (son(x)==son(y)) rotate(y),rotate(x); 54 else rotate(x),rotate(x); 55 } 56 } 57 } 58 inline int getkth(int k) { 59 int p = Root; 60 while (true) { 61 pushdown(p); 62 if (k==siz[ch[p][0]] + 1) return p; 63 if (ch[p][0] && k <= siz[ch[p][0]]) p = ch[p][0]; 64 else { 65 k -= ((ch[p][0] ? siz[ch[p][0]] : 0) + 1); 66 p = ch[p][1]; 67 } 68 } 69 } 70 int build(int l,int r) { 71 if (l > r) return 0; 72 int mid = (l + r) >> 1; 73 int tmp = build(l,mid-1); 74 fa[tmp] = mid;ch[mid][0] = tmp; 75 tmp = build(mid+1,r); 76 fa[tmp] = mid;ch[mid][1] = tmp; 77 pushup(mid); 78 return mid; 79 } 80 inline void Insert(int p) { 81 int x = read(); 82 char c; 83 for (int i=1; i<=x; ++i) {c = getchar();data[++tn] = (int)c;} 84 int tmp = build(tn-x+1,tn); 85 int L = getkth(p),R = getkth(p + 1); 86 splay(L,0);splay(R,L); 87 fa[tmp] = R;ch[R][0] = tmp; 88 pushup(R);pushup(L); 89 } 90 inline void Delete(int p,int x) { 91 int L = getkth(p),R = getkth(p+x+1); 92 splay(L,0);splay(R,L); 93 ch[R][0] = 0;fa[ch[R][0]] = 0; 94 pushup(R);pushup(L); 95 } 96 inline void rever(int l,int x) { 97 int r = l + x + 1; 98 int L = getkth(l),R = getkth(r); 99 splay(L,0);splay(R,L); 100 tag[ch[R][0]] ^= 1; 101 } 102 int main() { 103 104 int n = read(),now = 1,x; 105 char s[20]; 106 Root = 1;ch[1][1] = 2;fa[2] = 1;siz[1] = 2;siz[2] = 1;tn = 2; 107 while (n--) { 108 scanf("%s",s); 109 if (s[0]==‘I‘) Insert(now); 110 else if (s[0]==‘D‘) Delete(now,read()); 111 else if (s[0]==‘M‘) { 112 x = read();now = x + 1; 113 } 114 else if (s[0]==‘R‘) rever(now,read()); 115 else if (s[0]==‘G‘) { 116 x = getkth(now + 1);printf("%c\n",data[x]); 117 } 118 else if (s[0]==‘P‘) now --; 119 else if (s[0]==‘N‘) now ++; 120 } 121 return 0; 122 }