P4008 [NOI2003] 文本编辑器

P4008 [NOI2003] 文本编辑器

动态插入字符,动态删除字符,输出一个区间的字符串。

很明显可以直接用平衡树维护,当然也可以分块。

平衡树可以用 FHQTreap或者Splay ,这里用的是前者。

每次操作都可以看成分裂然后合并即可。

代码:

#include <bits/stdc++.h>
using namespace std;
template <typename T>
inline void read(T &x){
	x=0;char ch=getchar();bool f=false;
	while(!isdigit(ch)){if(ch=='-'){f=true;}ch=getchar();}
	while(isdigit(ch)){x=(x<<1)+(x<<3)+(ch^48);ch=getchar();}
	x=f?-x:x;
	return ;
}
template <typename T>
inline void write(T x){
	if(x<0) putchar('-'),x=-x;
	if(x>9) write(x/10);
	putchar(x%10^48);
	return ;
}
const int N=2e6+5;
int root,Cur;
int sta[N],top;
struct FHQTreap{
	int siz,key,ls,rs;
	char v;
	#define v(x) t[x].v
	#define siz(x) t[x].siz
	#define key(x) t[x].key
	#define ls(x) t[x].ls
	#define rs(x) t[x].rs
}t[N];
inline int NewNode(){return top?sta[top--]:++Cur;}
inline void Pushup(int x){
	siz(x)=siz(ls(x))+siz(rs(x))+1;
	return ;
}
void Split(int now,int &x,int &y,int k){
	if(!now) return x=y=0,void();
	if(siz(ls(now))>=k) y=now,Split(ls(now),x,ls(y),k),Pushup(y);
	else x=now,Split(rs(now),rs(x),y,k-siz(ls(now))-1),Pushup(x);
	return ;  
}
int Merge(int x,int y){
	if(!x||!y) return x+y;
	if(key(x)<=key(y)) return rs(x)=Merge(rs(x),y),Pushup(x),x;
	else return ls(y)=Merge(x,ls(y)),Pushup(y),y;
}
char str[N];
int Build(int l,int r){
	if(l>r) return 0;
	int mid=l+r>>1,cur=NewNode();key(cur)=rand();
	siz(cur)=1,v(cur)=str[mid];
	ls(cur)=Build(l,mid-1),rs(cur)=Build(mid+1,r);
	Pushup(cur);
	return cur;
}
inline void Del(int x){ls(x)=rs(x)=siz(x)=0;sta[++top]=x;return ;} 
void Delete(int x){
	if(ls(x)) Delete(ls(x));
	Del(x);
	if(rs(x)) Delete(rs(x));
	return ;
}
void Print(int x){
	if(ls(x)) Print(ls(x));
	putchar(v(x));
	if(rs(x)) Print(rs(x));
	return ;
}
int n;
int main(){
	read(n);int now=0;
	for(int i=1;i<=n;i++){
		char op[25];int k,x,y,z;
		scanf("%s",op);
		if(op[0]=='M') read(now);
		else if(op[0]=='I'){
			read(k);int tot=0;
			while(1){
				char ch=getchar();
				while(ch>126||ch<32||ch=='\n') ch=getchar();
				str[++tot]=ch;
				if(tot==k) break;
			} 
			char ch=getchar();
			Split(root,x,y,now);
			root=Merge(x,Merge(Build(1,k),y));
		}
		else if(op[0]=='D'){
			read(k);int w;
			Split(root,x,w,now);Split(w,y,z,k);
			Delete(y);
			root=Merge(x,z);
		}
		else if(op[0]=='G'){
			read(k);
			Split(root,x,y,now);Split(y,y,z,k);
			Print(y);putchar('\n');
			root=Merge(x,Merge(y,z));
		}
		else if(op[0]=='P') now--;
		else if(op[0]=='N') now++;
	}
	return 0;
}
posted @ 2021-04-16 10:54  __Anchor  阅读(77)  评论(0编辑  收藏  举报