BZOJ1269 [AHOI2006]文本编辑器editor splay

欢迎访问~原文出处——博客园-zhouzhendong

去博客园看该题解


题目传送门 - BZOJ1269


题意概括

  你要搞一个文本编辑器。

  主要支持一下操作:

  插入字符串、删除字符串、区间字符串翻转、输出光标后的一个字符。

  详细见原题。


题解

  splay板子题。

  一开始我是一个一个字符弄到splay里面去,结果Tle了。

  所以,我们要一段一段的插入。删除也同理,详见代码


 

代码

#include <cstring>
#include <algorithm>
#include <cstdio>
#include <cstdlib>
#include <cmath>
using namespace std;
const int MaxL=2100000;
char str[MaxL];
struct Splay{
	int root,cnt,fa[MaxL],son[MaxL][2],size[MaxL],val[MaxL],rev[MaxL];
	void clear(){
		root=cnt=0;
		memset(size,0,sizeof size);
		memset(son,0,sizeof son);
		memset(val,0,sizeof val);
		memset(rev,0,sizeof rev);
		memset(fa,0,sizeof fa);
	}
	void print(){
		puts("Splay.Print_________________");
		printf("root=%d\n",root);
		for (int i=1;i<=cnt;i++)
			printf("%d:fa=%d,son=(%d,%d),size=%d,val=%c,rev=%d\n"
			,i,fa[i],son[i][0],son[i][1],size[i],(char)val[i],rev[i]);
		puts("Splay.Print_Over============");
	}
	void dfs(int rt){
		pushdown(rt);
		if (son[rt][0])
			dfs(son[rt][0]);
		printf("%c",val[rt]);
		if (son[rt][1])
			dfs(son[rt][1]);
	}
	void printstr(){
		dfs(root);puts("");
	}
	void pushup(int x){size[x]=size[son[x][0]]+size[son[x][1]]+1;}
	void pushrev(int x){
		if (!x)
			return;
		rev[x]^=1;
		swap(son[x][0],son[x][1]);
	}
	void pushdown(int x){
		if (rev[x]){
			rev[x]=0;
			pushrev(son[x][0]);
			pushrev(son[x][1]);
		}
	}
	void pushadd(int x){
		if (fa[x])
			pushadd(fa[x]);
		pushdown(x);
	}
	int wson(int x){return son[fa[x]][1]==x;}
	void rotate(int x){
		if (!fa[x])
			return;
		int y=fa[x],z=fa[y],L=wson(x),R=L^1;
		if (z)
			son[z][wson(y)]=x;
		fa[x]=z,fa[y]=x,fa[son[x][R]]=y;
		son[y][L]=son[x][R],son[x][R]=y;
		pushup(y);
		pushup(x);
	}
	void splay(int x,int k){
		pushadd(x);
		if (k==0)
			root=x;
		while (fa[x]!=k){
			int y=fa[x],z=fa[y];
			if (z!=k)
				rotate(wson(x)==wson(y)?y:x);
			rotate(x);
		}
	}
	void splay(int x){
		splay(x,0);
	}
	void add(int &x,int pre,int befo,int v){
		if (!x){
			val[x=++cnt]=v,fa[x]=pre,size[x]=1;
			son[x][0]=son[x][1]=rev[x]=0;
			splay(x);
			return;
		}
		pushdown(x);
		size[x]++;
		if (size[son[x][0]]>=befo)
			add(son[x][0],x,befo,v);
		else
			add(son[x][1],x,befo-size[son[x][0]]-1,v);
    }
    void add(int befo,int v){add(root,0,befo,v);}
	void build(int &x,int pre,int L,int R){
		if (L>R)
			return;
		int mid=(L+R)>>1;
		fa[x=++cnt]=pre,val[x]=str[mid],rev[x]=0,size[x]=1,son[x][0]=son[x][1]=0;
		build(son[x][0],x,L,mid-1);
		build(son[x][1],x,mid+1,R);
		pushup(x);
	}
	int findkth(int x,int k){
		pushdown(x);
		if (k==size[son[x][0]]+1)
			return x;
		if (k<=size[son[x][0]])
			return findkth(son[x][0],k);
		else
			return findkth(son[x][1],k-size[son[x][0]]-1);
	}
	int findkth(int k){return findkth(root,k);}
	int findL(int x){
		pushdown(x);
		if (son[x][0])
			return findL(son[x][0]);
		return x;
	}
	int findR(int x){
		pushdown(x);
		if (son[x][1])
			return findR(son[x][1]);
		return x;
	}
	void erase(int L,int R){
		splay(findkth(L-1));
		splay(findkth(R+1),root);
		fa[son[son[root][1]][0]]=0;
		son[son[root][1]][0]=0;
		pushup(son[root][1]);
		pushup(root);
	}
}s;
int n,p;
int main(){
	scanf("%d",&n);
	s.clear();
	s.add(1,'#'),s.add(1,'#');
	p=0;
	for (int c=1;c<=n;c++){
//		s.print();
//		s.printstr();
		char op[10];
		int a;
		scanf("%s",op);
		if (op[0]=='M')
			scanf("%d",&p);
		else if (op[0]=='I'){
			scanf("%d%*c",&a);
			gets(str+1);
			s.splay(s.findkth(p+1));
			s.splay(s.findkth(p+2),s.root);
			s.build(s.son[s.son[s.root][1]][0],s.son[s.root][1],1,a);
		}
		else if (op[0]=='D'){
			scanf("%d",&a);
			s.erase(p+2,p+1+a);
		}
		else if (op[0]=='R'){
			scanf("%d",&a);
			s.splay(s.findkth(p+1));
			s.splay(s.findkth(p+a+2),s.findkth(p+1));
			s.pushrev(s.son[s.son[s.root][1]][0]);
		}
		else if (op[0]=='G')
			printf("%c\n",(char)s.val[s.findkth(p+2)]);
		else if (op[0]=='P')
			p--;
		else if (op[0]=='N')
			p++;
	}
	return 0;
}
/*
10
Insert 13
Balanced eert
Move 2
Delete 5
Next
Insert 7
 editor
Move 0
Get
Move 11
Rotate 4
Get
*/

  

转载于:https://www.cnblogs.com/zhouzhendong/p/BZOJ1269.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值