Splay chapter 1 : NOI 2003 editor
学了Splay 发现这是一个很有意思的东西 至少可以很高效的做一些操作 特别是它的神操作splay 通过对一个节点和它的前驱和后继的各种脑补splay
我们可以把需要操作的部分全部转到一棵树上 所以 orz Tarjan ... 然后做了一些入门的题 这里记下NOI2003 的 editor:
Problem:
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 16
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 16
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
Solution:
这个题据说是用什么块链可以做 当然我太弱了 捉不了 就把它当splay的练手题
整个题中光标的位置我都用树根来表示了 这样似乎会便于操作 然后按惯例加Super_root 这里用了Byvoid牛的一个巧办法 再加了个虚根 然后把所有char后移一位
对于Insert 我找它的后继结点 splay到root的rson 然后再其lson上加上字符(这里我把字符串建成了一棵树 好吧 其实是链)
对于Delete 找到区间右端点+1 splay到root 然后删其左子树
对于各种移动光标 直接search+splay
然后是Get 据说递归中序会爆栈 那么我就一个一个输出了
其中还有一些小细节 写的时候注意处理一下
Code:

1 #include <cstdio> 2 #include <cstdlib> 3 #include <cstring> 4 #include <cmath> 5 #include <iostream> 6 #include <algorithm> 7 #define rep(i,l,r) for(int i=l;i<=r;++i) 8 using namespace std; 9 int t,a,p = 1; 10 char cmd[15],s[1024 * 1024 + 10]; 11 class Splay{ 12 private: 13 struct Node{ 14 char ch; 15 int size,cnt; 16 Node *c[2],*fa; 17 Node(char _ch,Node *_fa){ 18 ch = _ch; fa = _fa; 19 cnt = 1; c[0] = c[1] = NULL; 20 } 21 int lsz() {return c[0] ? c[0]->size : 0;} 22 int rsz() {return c[1] ? c[1]->size : 0;} 23 }; 24 Node *root; 25 inline void upd(Node *tag){ 26 if(!tag) return; 27 tag->size = tag->cnt + tag->lsz() + tag->rsz(); 28 } 29 inline void zig(Node *tag,int d){ 30 Node *f = tag->fa; 31 int anti = 1 - d; 32 f->c[d] = tag->c[anti]; 33 if(f->c[d]) 34 f->c[d]->fa = f; 35 tag->fa = f->fa; 36 if(tag->fa->c[0] == f) 37 tag->fa->c[0] = tag; 38 else 39 tag->fa->c[1] = tag; 40 f->fa = tag; 41 tag->c[anti] = f; 42 upd(f); 43 } 44 inline int f(Node *tag){ 45 return tag->fa->c[1] == tag; 46 } 47 inline void splay(Node *tag,Node *goal) 48 { 49 while(tag->fa != goal){ 50 if(tag->fa->fa == goal) 51 zig(tag,f(tag)); 52 else{ 53 if(f(tag) == f(tag->fa)) 54 zig(tag->fa,f(tag->fa)),zig(tag,f(tag)); 55 else 56 zig(tag,f(tag)),zig(tag,f(tag)); 57 } 58 } 59 upd(tag); 60 } 61 inline Node *search(int key){ 62 Node *tag = root->c[0]; 63 while(tag && (key <= tag->lsz() || key > tag->lsz() + tag->cnt)){ 64 if(key > tag->lsz() + tag->cnt){ 65 key -= tag->lsz() + tag->cnt; tag = tag->c[1]; 66 }else 67 tag = tag->c[0]; 68 } 69 return tag; 70 } 71 public: 72 Splay() { root = new Node('#',NULL); Node *tmp = new Node('^',root); root->c[0] = tmp; upd(tmp);} 73 void insert(char *s){ 74 Node *chr = new Node(s[0],NULL),*tmp,*now,*tag = root->c[0]; 75 tmp = now = chr; chr->size = a; 76 rep(i,1,a - 1) 77 { 78 now = new Node(s[i],tmp); 79 tmp->c[1] = now; now->size = a - i; 80 tmp = now; 81 } 82 Node *z = tag->c[1]; 83 while(z && z->c[0]) z = z->c[0]; 84 if(z){ 85 splay(z,tag); 86 z->c[0] = chr; chr->fa = z; 87 upd(z); 88 }else{ 89 tag->c[1] = chr; chr->fa = tag; 90 upd(tag); 91 } 92 } 93 void trans(int x) {Node *tag = search(x); splay(tag,root);} 94 void erase(int l){ 95 Node *tag = root->c[0]; if(!tag) return; 96 Node *end = search(tag->lsz() + tag->cnt + l + 1); 97 if(end){ 98 splay(end,tag); end->c[0] = NULL; upd(end); 99 }else 100 tag->c[1] = NULL; 101 upd(tag); 102 } 103 void print(int l){ 104 Node *tag = root->c[0]; 105 rep(i,1,l){ 106 Node *tmp = search(p + i); 107 splay(tmp,tag); 108 putchar(tmp->ch); 109 } 110 putchar('\n'); 111 } 112 }tree; 113 int main() 114 { 115 freopen("input.in","r",stdin); freopen("output.out","w",stdout); 116 scanf("%d",&t); 117 rep(i,1,t) 118 { 119 scanf("%s %d",cmd,&a); 120 if(cmd[0] == 'I'){ 121 char c; 122 for (int i=0;i<a;) 123 { 124 while ((c=getchar())==10 || c==13); 125 s[i ++]=c; 126 } 127 tree.insert(s); continue; 128 } 129 if(cmd[0] == 'M'){ 130 tree.trans(a + 1); p = a + 1; continue; 131 } 132 if(cmd[0] == 'D'){ 133 tree.erase(a); continue; 134 } 135 if(cmd[0] == 'G'){ 136 tree.print(a); continue; 137 } 138 if(cmd[0] == 'P'){ 139 tree.trans(-- p); continue; 140 } 141 if(cmd[0] == 'N'){ 142 tree.trans(++ p); continue; 143 } 144 } 145 return 0; 146 }
然后 就没有然后了