http://www.lydsy.com/JudgeOnline/problem.php?id=1507
当练splay模板了,发现wjmzbmr的splay写得异常简介,学习了。orzzzzzzzzzzz!!!!!!
这个版本很好写的,比数组的好写多了。但是异常的慢啊T_T
这个版本的splay,会修改null的fa,但不影响结果,这点要记住。
#include
#include
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