bzoj 1269: [AHOI2006]文本编辑器editor (splay) [省选计划系列]

1269: [AHOI2006]文本编辑器editor

Time Limit: 10 Sec   Memory Limit: 162 MB
Submit: 3655   Solved: 1367
[ Submit][ Status][ Discuss]

Description

这些日子,可可不和卡卡一起玩了,原来可可正废寝忘食的想做一个简单而高效的文本编辑器。你能帮助他吗?为了明确任务目标,可可对“文本编辑器”做了一个抽象的定义:   文本:由0个或多个字符构成的序列。这些字符的ASCII码在闭区间[32, 126]内,也就是说,这些字符均为可见字符或空格。光标:在一段文本中用于指示位置的标记,可以位于文本的第一个字符之前,文本的最后一个字符之后或文本的某两个相邻字符之间。文本编辑器:为一个可以对一段文本和该文本中的一个光标进行如下七条操作的程序。如果这段文本为空,我们就说这个文本编辑器是空的。 编写一个程序: 建立一个空的文本编辑器。 从输入文件中读入一些操作指令并执行。 对所有执行过的GET操作,将指定的内容写入输出文件。

Input

输入文件中第一行是指令条数N,以下是需要执行的N个操作。除了回车符之外,输入文件的所有字符的ASCII码都在闭区间[32, 126]内。且行尾没有空格。

Output

依次对应输入文件中每条GET指令的输出,不得有任何多余的字符。

Sample Input

10
Insert 13
Balanced eert
Move 2
Delete 5
Next
Insert 7
editor
Move 0
Get
Move 11
Rotate 4
Get

Sample Output

B
t

HINT

对输入数据我们有如下假定: MOVE操作不超过50 000个,INSERT、DELETE和ROTATE操作作的总个数不超过6 000,GET操作不超过20 000个,PREV和NEXT操作的总个数不超过20 000。 所有INSERT插入的字符数之和不超过2M(1M=1 024*1 024)。 DELETE操作、ROTATE操作和GET操作执行时光标后必然有足够的字符。MOVE、PREV、NEXT操作不会把光标移动到非法位置。 输入文件没有错误。

Source

鸣谢seter重新制作数据


移动指针的那几个操作是逗你玩的。。。。。

其他几个操作....区间splay的基本操作.......


代码:
#include<iostream>
#include<algorithm>
#include<cstdlib>
#include<cstdio>
#include<cmath>
#include<cstring>
#include<string>
#include<climits>
#include<queue>
#include<stack>
#include<map>
#include<set>
#define N 5000020
using namespace std;
inline int read()
{
    int x=0,f=1;char ch;
    while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
    while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
    return x*f;
}
int n;char v[N];
int tr[N][2],fa[N],size[N],rt;bool rev[N];
void pushup(int k){size[k]=size[tr[k][0]]+size[tr[k][1]]+1;}
void pushdown(int k)
{
    if(rev[k])
    {
		int l=tr[k][0],r=tr[k][1];
		rev[l]^=1,rev[r]^=1,rev[k]^=1;
		swap(tr[k][0],tr[k][1]);
    }
}
void rotate(int x,int &k)
{
    int y=fa[x],z=fa[y],l,r;
    l=tr[y][1]==x;r=l^1;
    if(y==k)k=x;
    else tr[z][tr[z][1]==y]=x;
    fa[x]=z,fa[y]=x,fa[tr[x][r]]=y;
    tr[y][l]=tr[x][r],tr[x][r]=y;
    pushup(y);pushup(x);
}
void splay(int x,int &k)
{
    while(x!=k)
    {
		int y=fa[x],z=fa[y];
		if(y!=k)
		{
	   	 	if(tr[y][0]==x^tr[z][0]==y)
			rotate(x,k);
	    	else rotate(y,k);
		}rotate(x,k);
    }
}
int find(int k,int rk)
{
    if(rev[k])pushdown(k);
    int l=tr[k][0],r=tr[k][1];
    if(size[l]>=rk)return find(l,rk);
    else if(size[l]+1==rk)return k;
    else return find(r,rk-size[l]-1);
}
int now,pos,id[N];char a[N];
void move(int k){now=k;}
void new_node(int k,int x)
{v[k]=x;size[k]=1;rev[k]=0;return;}
int build(int l,int r)
{
	if(l>r)return 0;int mid=(l+r)>>1;
	id[mid]=++pos;new_node(id[mid],a[mid-1]);
	tr[id[mid]][0]=build(l,mid-1);fa[tr[id[mid]][0]]=id[mid];
	tr[id[mid]][1]=build(mid+1,r);fa[tr[id[mid]][1]]=id[mid];
	pushup(id[mid]);return id[mid];
}
void insert(int len)
{
	if(!rt){rt=build(1,len+2);return;}
    int x=find(rt,now+1);
    int y=find(rt,now+2);
    splay(x,rt);splay(y,tr[x][1]);
    tr[y][0]=build(2,len+1);
    pushup(y);splay(y,rt);
}
void del(int len)
{
    int x=find(rt,now+1);
    int y=find(rt,now+len+2);
    splay(x,rt);splay(y,tr[x][1]);
    tr[y][0]=0;splay(y,rt);
}
void rever(int len)
{
    int x=find(rt,now+1);
    int y=find(rt,now+len+2);
    splay(x,rt);splay(y,tr[x][1]);
    int k=tr[y][0];rev[k]^=1;
}
char get()
{
    int x=find(rt,now+2);
    return v[x];
}
void prev(){now--;}
void next(){now++;}
void getst(int len)
{
	char ch;
	while(ch<32||ch>126)ch=getchar();
	a[1]=ch;
	for(int i=2;i<=len;i++)
	{
		ch=getchar();
		a[i]=ch;
	}
}
/*
1000
Insert 3
aba
Move 0
Get
Move 2
Insert 1
c
Get
Rotate 2
Get
*/
int main()
{
    n=read();char ss[10];
    for(int i=1;i<=n;i++)
    {
		scanf("%s",ss);
		if(ss[0]=='M')
		{
	  		int x=read();
	 	   	move(x);
		}
		else if(ss[0]=='I')
		{
			int x=read();
		    getst(x);
		    insert(x);
		}
		else if(ss[0]=='D')
		{	
		    int x=read();
		    del(x);
		}
		else if(ss[0]=='R')	
		{
		    int x=read();
		    rever(x);
		}
		else if(ss[0]=='G')printf("%c\n",get());
		else if(ss[0]=='P')prev();
		else next();
    }
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值