1269: [AHOI2006]文本编辑器editor
Time Limit: 10 Sec
Memory Limit: 162 MB
Submit: 2678
Solved: 996
[ 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
这道题很显然是一道Splay维护区间题,只不过这里的值是字符而不是整数,其实道理是一样的。
我最初提交时输入写scanf(“%d\n”,&n)结果是TLE,后来改成scanf(“%d%*c”,&n)结果就对了。
注:在scanf中如果%后加*表示读入后不赋给相应的变量,即跳过该输入值。
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cmath>
#include<cstring>
#include<algorithm>
#define F(i,j,n) for(int i=j;i<=n;i++)
#define D(i,j,n) for(int i=j;i>=n;i--)
#define LL long long
#define pa pair<int,int>
#define MAXN 2100000
#define INF 1000000000
#define key c[c[rt][1]][0]
using namespace std;
int pos=1,rt=0,tot=0,n,x,c[MAXN][2],s[MAXN],fa[MAXN];
char v[MAXN],op[10],ch[MAXN];
bool rev[MAXN];
inline void pushup(int k)
{
if (!k) return;
s[k]=s[c[k][0]]+s[c[k][1]]+1;
}
inline void update(int k)
{
if (!k) return;
rev[k]^=1;
swap(c[k][0],c[k][1]);
}
inline void pushdown(int k)
{
if (!k) return;
if (rev[k])
{
update(c[k][0]);update(c[k][1]);
rev[k]=0;
}
}
inline void rotate(int x,int &k)
{
int y=fa[x],z=fa[y],l=(c[y][1]==x),r=l^1;
if (y==k) k=x;
else c[z][c[z][1]==y]=x;
fa[x]=z;fa[y]=x;fa[c[x][r]]=y;
c[y][l]=c[x][r];c[x][r]=y;
pushup(y);pushup(x);
}
inline void splay(int x,int &k)
{
while (x!=k)
{
int y=fa[x],z=fa[y];
if (y!=k)
{
if ((c[y][0]==x)^(c[z][0]==y)) rotate(x,k);
else rotate(y,k);
}
rotate(x,k);
}
}
inline int find(int k,int rank)
{
pushdown(k);
int l=c[k][0],r=c[k][1];
if (s[l]+1==rank) return k;
else if (s[l]>=rank) return find(l,rank);
else return find(r,rank-s[l]-1);
}
inline void split(int l,int r)
{
int x=find(rt,l-1),y=find(rt,r+1);
splay(x,rt);splay(y,c[rt][1]);
}
inline void newnode(int &k,char ch,int last)
{
k=++tot;
fa[k]=last;
v[k]=ch;
c[k][0]=c[k][1]=rev[k]=0;
s[k]=1;
}
inline void ins(int &k,int l,int r,int last)
{
int mid=(l+r)>>1;
newnode(k,ch[mid],last);
if (l<mid) ins(c[k][0],l,mid-1,k);
if (mid<r) ins(c[k][1],mid+1,r,k);
pushup(k);
}
inline void solveins()
{
scanf("%d%*c",&x);
gets(ch);
split(pos+1,pos);
ins(key,0,x-1,c[rt][1]);
pushup(c[rt][1]);pushup(rt);
}
inline void solvedel()
{
scanf("%d%*c",&x);
split(pos+1,pos+x);
fa[key]=0;key=0;
pushup(c[rt][1]);pushup(rt);
}
inline void solverev()
{
scanf("%d%*c",&x);
split(pos+1,pos+x);
update(key);
}
int main()
{
newnode(rt,'*',0);newnode(c[rt][1],'*',rt);pushup(rt);
scanf("%d%*c",&n);
F(i,1,n)
{
scanf("%s%*c",op);
if (op[0]=='M') {scanf("%d%*c",&x);pos=x+1;}
else if (op[0]=='I') solveins();
else if (op[0]=='D') solvedel();
else if (op[0]=='R') solverev();
else if (op[0]=='G') printf("%c\n",v[find(rt,pos+1)]);
else if (op[0]=='P') pos--;
else pos++;
}
}