[NOI2003]文本编辑器

题目:洛谷P4008、BZOJ1507。

题目大意:
一堆操作。
1. 光标移动到指定位置
2. 在光标后插入一串字符
3. 在光标后删除一串字符
4. 光标前移
5. 光标后移
6. 输出光标后的一串字符
解题思路:
非旋Treap即可,插入时一个一个字符插也没什么问题,开O2就可以过(BZOJ过不去)。

C++ Code:

#include<bits/stdc++.h>
int t,rt=0,cnt=0,n,gb;
struct node{
	int r,ls,rs,sz;
	char s;
}a[5000005];
char opt;
inline void update(int x){a[x].sz=a[a[x].ls].sz+a[a[x].rs].sz+1;}
int merge(int x,int y){
	if(!x||!y)return x+y;
	if(a[x].r<a[y].r){
		a[x].rs=merge(a[x].rs,y);
		update(x);
		return x;
	}else{
		a[y].ls=merge(x,a[y].ls);
		update(y);
		return y;
	}
}
void split(int u,int k,int& x,int& y){
	if(k==0){x=0,y=u;return;}
	if(a[u].sz==k){x=u,y=0;return;}
	if(a[a[u].ls].sz>=k)split(a[u].ls,k,x,a[u].ls),y=u;else
	split(a[u].rs,k-a[a[u].ls].sz-1,a[u].rs,y),x=u;
	update(u);
}
void print(int now){
	if(!now)return;
	print(a[now].ls);
	putchar(a[now].s);
	print(a[now].rs);
}
inline int readint(){
	int c=getchar(),d=0;
	for(;!isdigit(c);c=getchar());
	for(;isdigit(c);c=getchar())
	d=(d<<3)+(d<<1)+(c^'0');
	return d;
}
int main(){
	srand(20170607);
	memset(a,0,sizeof a);
	gb=0;
	for(t=readint();t--;){
		opt=getchar();
		for(;!isalpha(opt);opt=getchar());
		if(opt=='I'){
			n=readint();
			int oldgb=gb;
			while(n--){
				char c=getchar();
				while(c<32||c>126)c=getchar();
				a[++cnt]=(node){rand(),0,0,1,c};
				int x,y;
				split(rt,gb++,x,y);
				rt=merge(merge(x,cnt),y);
			}
			gb=oldgb;
		}else
		if(opt=='D'){
			n=readint();
			int x,y,z;
			split(rt,gb,x,y);
			split(y,n,y,z);
			rt=merge(x,z);
		}else
		if(opt=='M')gb=readint();else
		if(opt=='P')--gb,getchar(),getchar(),getchar();else
		if(opt=='N')++gb,getchar(),getchar(),getchar();else{
			n=readint();
			int x,y,z;
			split(rt,gb,x,y);
			split(y,n,y,z);
			print(y);putchar('\n');
			rt=merge(merge(x,y),z);
		}
		//print(rt);
	}
	return 0;
}

以下为笛卡尔树建树版本,跑的快了不止一点点,能在BZOJ上过了。

C++ Code:

#include<bits/stdc++.h>
int t,rt=0,cnt=0,n,gb,top=0,sta[5000005];
struct node{
	int r,ls,rs,sz;
	char s;
}a[5000005];
char opt,s[5000005];
inline void update(int x){a[x].sz=a[a[x].ls].sz+a[a[x].rs].sz+1;}
int merge(int x,int y){
	if(!x||!y)return x+y;
	if(a[x].r<a[y].r){
		a[x].rs=merge(a[x].rs,y);
		update(x);
		return x;
	}else{
		a[y].ls=merge(x,a[y].ls);
		update(y);
		return y;
	}
}
void split(int u,int k,int& x,int& y){
	if(k==0){x=0,y=u;return;}
	if(a[u].sz==k){x=u,y=0;return;}
	if(a[a[u].ls].sz>=k)split(a[u].ls,k,x,a[u].ls),y=u;else
	split(a[u].rs,k-a[a[u].ls].sz-1,a[u].rs,y),x=u;
	update(u);
}
void print(int now){
	if(!now)return;
	print(a[now].ls);
	putchar(a[now].s);
	print(a[now].rs);
}
inline int readint(){
	int c=getchar(),d=0;
	for(;!isdigit(c);c=getchar());
	for(;isdigit(c);c=getchar())
	d=(d<<3)+(d<<1)+(c^'0');
	return d;
}
int build(int n){
	int x,pre;
	for(int i=1;i<=n;++i){
		a[x=++cnt]=(node){rand(),0,0,1,s[i]};
		for(pre=0;top&&a[sta[top]].r>a[x].r;--top)update(pre=sta[top]);
		if(top)a[sta[top]].rs=x;
		a[sta[++top]=x].ls=pre;
	}
	while(top)update(sta[top--]);
	return sta[1];
}
int main(){
	srand(20170607);
	memset(a,0,sizeof a);
	gb=0;
	for(t=readint();t--;){
		opt=getchar();
		for(;!isalpha(opt);opt=getchar());
		if(opt=='I'){
			n=readint();
			for(int i=1;i<=n;++i){
				char c=getchar();
				while(c<32||c>126)c=getchar();
				s[i]=c;
			}
			int x=build(n),y,z;
			split(rt,gb,y,z);
			rt=merge(merge(y,x),z);
		}else
		if(opt=='D'){
			n=readint();
			int x,y,z;
			split(rt,gb,x,y);
			split(y,n,y,z);
			rt=merge(x,z);
		}else
		if(opt=='M')gb=readint();else
		if(opt=='P')--gb,getchar(),getchar(),getchar();else
		if(opt=='N')++gb,getchar(),getchar(),getchar();else{
			n=readint();
			int x,y,z;
			split(rt,gb,x,y);
			split(y,n,y,z);
			print(y);putchar('\n');
			rt=merge(merge(x,y),z);
		}
		//print(rt);
	}
	return 0;
}

 

posted @ 2018-04-13 14:04  Mrsrz  阅读(296)  评论(0编辑  收藏  举报