[BZOJ1507] [NOI2003] Editor (splay)
Description
Input
输入文件editor.in的第一行是指令条数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秒。
Output
输出文件editor.out的每行依次对应输入文件中每条GET指令的输出。
Sample Input
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
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
Sample Output
.\/.
abcde^_^f.\/.ghijklmno
abcde^_^f.\/.ghijklmno
HINT
Source
Solution
splay的区间操作。
1 #include <bits/stdc++.h> 2 using namespace std; 3 struct spaly 4 { 5 char key; 6 int siz, fa, c[2]; 7 }a[2100005]; 8 char inss[2100005]; 9 int ptot; 10 11 void push_up(int k) 12 { 13 a[k].siz = a[a[k].c[0]].siz + a[a[k].c[1]].siz + 1; 14 } 15 16 void rotate(int &k, int x) 17 { 18 int y = a[x].fa, z = a[y].fa; 19 int dy = a[y].c[1] == x, dz = a[z].c[1] == y; 20 if(k == y) k = x, a[x].fa = z; 21 else a[z].c[dz] = x, a[x].fa = z; 22 a[y].c[dy] = a[x].c[!dy], a[a[x].c[!dy]].fa = y; 23 a[x].c[!dy] = y, a[y].fa = x; 24 push_up(y); 25 } 26 27 void splay(int &k, int x) 28 { 29 while(k != x) 30 { 31 int y = a[x].fa, z = a[y].fa; 32 if(k != y) 33 if(a[y].c[1] == x ^ a[z].c[1] == y) rotate(k, x); 34 else rotate(k, y); 35 rotate(k, x); 36 } 37 push_up(x); 38 } 39 40 int find(int k, int x) 41 { 42 if(!k || x == a[a[k].c[0]].siz + 1) return k; 43 if(x <= a[a[k].c[0]].siz) return find(a[k].c[0], x); 44 return find(a[k].c[1], x - a[a[k].c[0]].siz - 1); 45 } 46 47 void build(int &k, int fa, int i, int m) 48 { 49 if(i == m) return; 50 k = ++ptot, a[k].fa = fa, a[k].key = inss[i]; 51 build(a[k].c[1], k, i + 1, m); 52 push_up(k); 53 } 54 55 void printf(int k) 56 { 57 if(!k) return; 58 printf(a[k].c[0]), printf("%c", a[k].key), printf(a[k].c[1]); 59 } 60 61 int main() 62 { 63 int n, m, root = 1, pos = 0, ctot = 0; 64 char op[10]; 65 scanf("%d", &n), ptot = 2; 66 a[1].c[1] = 2, a[1].siz = 2, a[2].siz = 1, a[2].fa = 1; 67 while(n--) 68 { 69 scanf("%s", op); 70 if(op[0] == 'M') scanf("%d", &pos); 71 if(op[0] == 'I') 72 { 73 scanf("%d", &m), ctot += m; 74 for(int i = 0; i < m; i++) 75 { 76 inss[i] = getchar(); 77 if(inss[i] < 32 || inss[i] > 126) i--; 78 } 79 splay(root, find(root, pos + 1)); 80 splay(a[root].c[1], find(root, pos + 2)); 81 build(a[a[root].c[1]].c[0], a[root].c[1], 0, m); 82 push_up(a[root].c[1]), push_up(root); 83 } 84 if(op[0] == 'D') 85 { 86 scanf("%d", &m), m = min(m, ctot - pos); 87 splay(root, find(root, pos + 1)); 88 splay(a[root].c[1], find(root, pos + m + 2)); 89 a[a[root].c[1]].c[0] = 0, ctot -= m; 90 push_up(a[root].c[1]), push_up(root); 91 } 92 if(op[0] == 'G') 93 { 94 scanf("%d", &m), m = min(m, ctot - pos); 95 splay(root, find(root, pos + 1)); 96 splay(a[root].c[1], find(root, pos + m + 2)); 97 printf(a[a[root].c[1]].c[0]), puts(""); 98 } 99 if(op[0] == 'P') pos--; 100 if(op[0] == 'N') pos++; 101 } 102 return 0; 103 }