【BZOJ】1507: [NOI2003]Editor(Splay)

http://www.lydsy.com/JudgeOnline/problem.php?id=1507php

當練splay模板了,發現wjmzbmr的splay寫得異常簡介,學習了。orzzzzzzzzzzz!!!!!!node

這個版本很好寫的,比數組的好寫多了。可是異常的慢啊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

Sample Output

.\/.
abcde^_^f.\/.ghijklmno

HINT

Source

相關文章
相關標籤/搜索