【BZOJ】1269: [AHOI2006]文本编辑器editor(Splay)
http://www.lydsy.com/JudgeOnline/problem.php?id=1269
这题RE2次啊,好不爽啊,我一直以为是splay的问题,其实是数组开小了。。。。。。(我老犯这种低级错啊喂。。
和1507一样是模板题,指针版的速度依旧不行,,,,太慢了。
#include <string> #include <cstdio> #include <algorithm> using namespace std; char strI[1024*1024*2+100]; struct Splay { struct node{ node *ch[2], *fa; char key; int size, rev; node() { ch[0]=ch[1]=fa=NULL; rev=size=key=0; } void pushup() { size=ch[0]->size+ch[1]->size+1; } void pushdown() { if(rev) { node *c0=ch[0], *c1=ch[1]; setc(c1, 0); setc(c0, 1); ch[0]->rev ^= 1; ch[1]->rev^=1; rev=0; } } 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; null->ch[0]=null->ch[1]=null->fa=null; 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->pushdown(); r->pushdown(); 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) { r->pushdown(); 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; node *t=root; for(t->pushdown(); ; t->pushdown()) { 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->pushdown(); t->pushup(); splay(t, null); } void remove(int at, int n) { node *t=getrange(at, at+n+1); t->setc(null, 0); t->pushdown(); 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 setrev(int at, int n) { node *t=getrange(at, at+n+1); t->ch[0]->rev^=1; t->pushdown(); } void print(node *r) { if(r==null) return; r->pushdown(); 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') { splay.print(at, 1); } else if(s[0]=='R') { scanf("%d", &t); splay.setrev(at, t); } else if(s[0]=='P') --at; else if(s[0]=='N') ++at; } return 0; }
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