[NOI2003]文本编辑器/[AHOI2006]文本编辑器

XII.初级版:[NOI2003]文本编辑器;进阶版:[AHOI2006]文本编辑器

两道题操作基本一致,唯一的区别就是进阶版多了一个翻转操作,因此干脆合在一起讲。

可以使用splay或fhq treap通过。个人认为fhq treap更加直观。

光标的位置,我们用一个值\(tar\)表示。

Move/Next/Prev:直接修改\(tar\)的值即可。

Insert:笛卡尔树\(O(n)\)建树并插入。

Deletesplit出有效区间然后删掉即可。可以采取空间回收,这是很好的习惯,因为你不知道会不会RE/MLE。

Get:直接输出split后右半部最靠左那个地方的字符即可。

Rotate:fhq treap上打区间翻转的tag即可。

[NOI2003]文本编辑器代码:

#include<bits/stdc++.h>
using namespace std;
int n,rt,cnt,bin[5001000],tp,tar,stk[5001000],bd;
char s[5001000];
void getstring(int len){
	char c=getchar();
	for(int i=0;i<len;i++){
		while(c>126||c<32)c=getchar();
		s[i]=c,c=getchar();
	}
}
int read(){
	int x=0;
	char c=getchar();
	while(c>'9'||c<'0')c=getchar();
	while(c>='0'&&c<='9')x=x*10+c-48,c=getchar();
	return x;
}
struct treap{
	int lson,rson,rd,sz;
	char ch;
}t[5001000];
int newnode(char ch){
	int x=tp?bin[tp--]:++cnt;
	t[x].ch=ch,t[x].lson=t[x].rson=0,t[x].sz=1,t[x].rd=rand()*rand();
	return x;
}
void pushup(int x){
	t[x].sz=1;
	if(t[x].lson)t[x].sz+=t[t[x].lson].sz;
	if(t[x].rson)t[x].sz+=t[t[x].rson].sz;
}
void split(int x,int k,int &u,int &v){
	if(!x){u=v=0;return;}
	if(t[t[x].lson].sz>=k)v=x,split(t[x].lson,k,u,t[x].lson);
	else u=x,split(t[x].rson,k-t[t[x].lson].sz-1,t[x].rson,v);
	pushup(x);
}
int merge(int x,int y){
	if(!x||!y)return x+y;
	if(t[x].rd>t[y].rd){t[x].rson=merge(t[x].rson,y),pushup(x);return x;}
	else{t[y].lson=merge(x,t[y].lson),pushup(y);return y;}
}
void iterate(int x){
	if(!x)return;
	iterate(t[x].lson);
	putchar(t[x].ch);
	iterate(t[x].rson);
}
void oldnode(int x){
	if(!x)return;
	oldnode(t[x].lson),oldnode(t[x].rson),bin[++tp]=x;
}
int build(int len){
	int las;
	for(int i=0;i<len;i++){
		int x=newnode(s[i]);
		las=0;
		while(bd&&t[stk[bd]].rd<t[x].rd)pushup(stk[bd]),las=stk[bd--];
		if(bd)t[stk[bd]].rson=x;
		t[stk[++bd]=x].lson=las;
	}
	while(bd)pushup(stk[bd--]);
	return stk[1];
} 
void Move(){tar=read();}
void Insert(){
	int len=read();
	getstring(len);
	int a,b;
	split(rt,tar,a,b);
	rt=merge(merge(a,build(len)),b);
}
void Delete(){
	int len=read();
	int a,b,c;
	split(rt,tar,a,b);
	split(b,len,b,c);
	oldnode(b);
	rt=merge(a,c);
}
void Get(){
	int len=read();
	int a,b,c;
	split(rt,tar,a,b);
	split(b,len,b,c);
	iterate(b);putchar('\n'); 
	rt=merge(merge(a,b),c);
}
void Prev(){tar--;}
void Next(){tar++;}
int main(){
	n=read();
	while(n--){
		scanf("%s",s);
		if(s[0]=='I')Insert();
		else if(s[0]=='M')Move();
		else if(s[0]=='D')Delete();
		else if(s[0]=='G')Get();
		else if(s[0]=='P')Prev();
		else if(s[0]=='N')Next();
	}
	return 0;
}

[AHOI2006]文本编辑器代码:

#include<bits/stdc++.h>
using namespace std;
int n,stk[5001000],tp,bin[5001000],bd,cnt,tar,rt;
char s[5001000];
void getstring(int len){
	for(int i=0;i<len;i++)s[i]=getchar(); 
}
int read(){
	int x=0;
	char c=getchar();
	while(c>'9'||c<'0')c=getchar();
	while(c>='0'&&c<='9')x=(x<<3)+(x<<1)+(c^48),c=getchar();
	return x;
}
struct treap{
	int lson,rson,rd,sz;
	char ch;
	bool rev;
}t[5001000];
int newnode(char ch){
	int x=tp?bin[tp--]:++cnt;
	t[x].lson=t[x].rson=0,t[x].rd=rand()*rand(),t[x].sz=1,t[x].ch=ch,t[x].rev=false;
	return x;
}
void oldnode(int x){
	if(!x)return;
	oldnode(t[x].lson),oldnode(t[x].rson),bin[++tp]=x;
}
void pushup(int x){
	t[x].sz=1;
	if(t[x].lson)t[x].sz+=t[t[x].lson].sz;
	if(t[x].rson)t[x].sz+=t[t[x].rson].sz;
}
void REV(int x){
	swap(t[x].lson,t[x].rson),t[x].rev^=1;
}
void pushdown(int x){
	if(!t[x].rev)return;
	REV(t[x].lson),REV(t[x].rson),t[x].rev=false;
}
int merge(int x,int y){
	if(!x||!y)return x+y;
	if(t[x].rd>t[y].rd){pushdown(x),t[x].rson=merge(t[x].rson,y),pushup(x);return x;}
	else{pushdown(y),t[y].lson=merge(x,t[y].lson),pushup(y);return y;}
} 
void split(int x,int k,int &u,int &v){
	if(!x){u=v=0;return;}
	pushdown(x);
	if(t[t[x].lson].sz>=k)v=x,split(t[x].lson,k,u,t[x].lson);
	else u=x,split(t[x].rson,k-t[t[x].lson].sz-1,t[x].rson,v);
	pushup(x);
}
void Insert(){
	int len=read();
	getstring(len);
	for(int i=0;i<len;i++){
		int x=newnode(s[i]),las=0;
		while(bd&&t[stk[bd]].rd<t[x].rd)pushup(stk[bd]),las=stk[bd--];
		if(bd)t[stk[bd]].rson=x;
		t[stk[++bd]=x].lson=las;
	}
	while(bd)pushup(stk[bd--]);
	int a,b;
	split(rt,tar,a,b);
	rt=merge(merge(a,stk[1]),b);
}
void Delete(){
	int len=read();
	int a,b,c;
	split(rt,tar,a,b);
	split(b,len,b,c);
	rt=merge(a,c),oldnode(b);
}
void Rotate(){
	int len=read();
	int a,b,c;
	split(rt,tar,a,b);
	split(b,len,b,c);
	REV(b),rt=merge(merge(a,b),c);
}
void Move(){tar=read();}
void Next(){tar++;}
void Prev(){tar--;}
void leftmost(int x){
	pushdown(x);
	if(!t[x].lson){
		putchar(t[x].ch);
		if(t[x].ch!='\n')putchar('\n');	
	}else leftmost(t[x].lson);
}
/*
void iterate(int x){
	if(!x)return;
	pushdown(x);
	iterate(t[x].lson);
	putchar(t[x].ch);
	iterate(t[x].rson);
}
*/
void Get(){
	int a,b;
	split(rt,tar,a,b);
	leftmost(b);
	rt=merge(a,b);
}
int main(){
	n=read();
	while(n--){
		scanf("%s",s);
		if(s[0]=='M')Move();
		else if(s[0]=='I')Insert();
		else if(s[0]=='D')Delete();
		else if(s[0]=='R')Rotate();
		else if(s[0]=='G')Get();
		else if(s[0]=='P')Prev();
		else if(s[0]=='N')Next();
//		iterate(rt),putchar('\n');
	}
	return 0;
}

原文地址:https://www.cnblogs.com/Troverld/p/14611213.html