【BZOJ】1507: [NOI2003]Editor(Splay)
http://www.lydsy.com/JudgeOnline/problem.php?id=1507
当练splay模板了,发现wjmzbmr的splay写得异常简介,学习了。orzzzzzzzzzzz!!!!!!
这个版本很好写的,比数组的好写多了。但是异常的慢啊T_T
这个版本的splay,会修改null的fa,但不影响结果,这点要记住。
#include <string> #include <cstdio> using namespace std; char strI[1024*1024+100]; struct Splay { struct node{ node *ch[2], *fa; char key; int size; node() { ch[0]=ch[1]=fa=NULL; size=key=0; } void pushup() { size=ch[0]->size+ch[1]->size+1; } bool d() { return this==fa->ch[1]; } void setc(node *c, int _d) { ch[_d]=c; c->fa=this; } }*null, *root; Splay() { null=new node; root=null; root=newnode(0); node *t=newnode(0); root->setc(t, 1); root->pushup(); } node* newnode(char key) { node *ret=new node; ret->ch[0]=ret->ch[1]=ret->fa=null; ret->key=key; ret->size=1; return ret; } void rot(node *r) { node *fa=r->fa; bool d=r->d(); fa->fa->setc(r, fa->d()); fa->setc(r->ch[!d], d); r->setc(fa, !d); fa->pushup(); if(fa==root) root=r; } void splay(node *r, node *fa) { while(r->fa!=fa) { if(r->fa->fa==fa) rot(r); else r->d()==r->fa->d()?(rot(r->fa), rot(r)):(rot(r), rot(r)); } r->pushup(); } node* sel(int k) { int s; for(node *t=root; ;) { s=t->ch[0]->size; if(s==k) return t; t=t->ch[k>s]; if(k>s) k-=s+1; } } node* getrange(int l, int r) { node *left=sel(l); splay(left, null); node *right=sel(r); splay(right, left); return right; } void insert(int at, int cur) { node *t=getrange(at, at+1); t->setc(build(0, cur), 0); t->pushup(); splay(t, null); } void remove(int at, int n) { node *t=getrange(at, at+n+1); t->setc(null, 0); t->pushup(); splay(t, null); } node* build(int l, int r) { if(l>=r) return null; int m=(l+r)>>1; node *t=newnode(strI[m]); t->setc(build(l, m), 0); t->setc(build(m+1, r), 1); t->pushup(); return t; } void print(node *r) { if(r==null) return; print(r->ch[0]); printf("%c", r->key); print(r->ch[1]); } void print(int at, int n) { node *t=getrange(at, at+n+1); print(t->ch[0]); printf("\n"); } }splay; char s[10]; int main() { int n, t, cur, at=0; scanf("%d", &n); while(n--) { scanf("%s", s); if(s[0]=='I') { scanf("%d", &t); cur=0; while(t--) { while(strI[cur]=getchar(), strI[cur]=='\n'); cur++; } splay.insert(at, cur); } else if(s[0]=='M') { scanf("%d", &at); } else if(s[0]=='D') { scanf("%d", &t); splay.remove(at, t); } else if(s[0]=='G') { scanf("%d", &t); splay.print(at, t); } else if(s[0]=='P') --at; else if(s[0]=='N') ++at; } return 0; }
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
HINT
Source
博客地址:www.cnblogs.com/iwtwiioi 本文为博主原创文章,未经博主允许不得转载。一经发现,必将追究法律责任。