1507: [NOI2003]Editor(块状链表)
1507: [NOI2003]Editor
Time Limit: 5 Sec Memory Limit: 162 MBSubmit: 4157 Solved: 1677
[Submit][Status][Discuss]
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
code
1 #include<cstdio> 2 #include<cstring> 3 4 const int MAXL = 2100000; 5 const int Block_size = 5010; 6 const int Block_num = 600; 7 int Number[Block_num],Tot; 8 int nxt[Block_num],siz[Block_num]; 9 char data[Block_num][Block_size]; 10 char str[MAXL],s[20]; 11 12 void Init() { 13 for (int i=1; i<Block_num; ++i) 14 Number[i] = i; 15 Tot = 1; 16 nxt[0] = -1;siz[0] = 0; 17 } 18 int Getnum() { 19 return Number[Tot++]; 20 } 21 void Delnum(int x) { 22 Number[--Tot] = x; 23 } 24 int find(int &pos) { 25 int k = 0; 26 while (k != -1 && pos > siz[k]) { 27 pos -= siz[k]; 28 k = nxt[k]; 29 } 30 return k; 31 } 32 void Madenews(int cur,int news,int num,char str[]) { 33 if (news!=-1) { 34 nxt[news] = nxt[cur]; 35 siz[news] = num; 36 memcpy(data[news],str,num); 37 } 38 nxt[cur] = news; 39 } 40 void split(int cur,int pos) { 41 if (cur==-1 || pos==siz[cur]) return ; 42 int news = Getnum(); 43 Madenews(cur,news,siz[cur]-pos,data[cur]+pos); 44 siz[cur] = pos; 45 } 46 void Merge(int x,int y) { 47 memcpy(data[x]+siz[x],data[y],siz[y]); 48 siz[x] += siz[y]; 49 nxt[x] = nxt[y]; 50 Delnum(y); 51 } 52 void Maintain() { 53 int cur = 0; 54 while (cur != -1) { 55 int p = nxt[cur]; 56 while (p != -1 && siz[cur] + siz[p] <= Block_size) { 57 Merge(cur,p); 58 p = nxt[cur]; 59 } 60 cur = nxt[cur]; 61 } 62 } 63 void Insert(int pos,int num,char str[]) { 64 int cur = find(pos); 65 split(cur,pos); 66 int cnt = 0; 67 while (cnt + Block_size <= num) { 68 int news = Getnum(); 69 Madenews(cur,news,Block_size,str+cnt); 70 cur = news; 71 cnt += Block_size; 72 } 73 if (num - cnt) { 74 int news = Getnum(); 75 Madenews(cur,news,num-cnt,str+cnt); 76 } 77 Maintain(); 78 } 79 void Erase(int pos,int num) { 80 int cur = find(pos); 81 split(cur,pos); 82 int p = nxt[cur]; 83 while (p != -1 && num > siz[p]) { 84 num -= siz[p]; 85 p = nxt[p]; 86 } 87 split(p,num); 88 p = nxt[p]; 89 for (int i=nxt[cur]; i!=p; i=nxt[cur]) { 90 nxt[cur] = nxt[i]; 91 Delnum(i); 92 } 93 Maintain(); 94 } 95 void Getdata(int pos,int num,char str[]) { 96 int cur = find(pos); 97 int cnt = siz[cur] - pos; 98 if (num < cnt) cnt = num; 99 memcpy(str,data[cur]+pos,cnt); 100 int tmp = nxt[cur]; 101 while (tmp!=-1 && cnt+siz[tmp] <= num) { 102 memcpy(str+cnt,data[tmp],siz[tmp]); 103 cnt += siz[tmp]; 104 tmp = nxt[tmp]; 105 } 106 if (num - cnt && tmp != -1) 107 memcpy(str+cnt,data[tmp],num-cnt); 108 str[num] = '\0'; 109 } 110 int main() { 111 Init(); 112 int Nowpos = 0,opt,num; 113 scanf("%d",&opt); 114 while (opt) { 115 opt--; 116 scanf("%s",s); 117 if (s[0]=='M') scanf("%d",&Nowpos); 118 else if (s[0]=='I') { 119 scanf("%d",&num); 120 for (int i=0; i<num; ++i) { 121 scanf("%c",&str[i]); 122 if (str[i]<32 || str[i]>126) --i; 123 } 124 Insert(Nowpos,num,str); 125 } 126 else if (s[0]=='D') { 127 scanf("%d",&num); 128 Erase(Nowpos,num); 129 } 130 else if (s[0]=='G') { 131 scanf("%d",&num); 132 Getdata(Nowpos,num,str); 133 printf("%s\n",str); 134 } 135 else if (s[0]=='P') --Nowpos; 136 else ++Nowpos; 137 } 138 return 0; 139 }