1269: [AHOI2006]文本編輯器editor
Time Limit: 10 Sec Memory Limit: 162 MBSubmit: 3655 Solved: 1367
[Submit][Status][Discuss]
Description
這些日子,可可不和卡卡一起玩了,原來可可正廢寢忘食的想做一個簡單而高效的文本編輯器。你能幫助他嗎?爲了明確任務目標,可可對“文本編輯器”做了一個抽象的定義: 文本:由0個或多個字符構成的序列。這些字符的ASCII碼在閉區間[32, 126]內,也就是說,這些字符均爲可見字符或空格。光標:在一段文本中用於指示位置的標記,可以位於文本的第一個字符之前,文本的最後一個字符之後或文本的某兩個相鄰字符之間。文本編輯器:爲一個可以對一段文本和該文本中的一個光標進行如下七條操作的程序。如果這段文本爲空,我們就說這個文本編輯器是空的。 編寫一個程序: 建立一個空的文本編輯器。 從輸入文件中讀入一些操作指令並執行。 對所有執行過的GET操作,將指定的內容寫入輸出文件。
Input
輸入文件中第一行是指令條數N,以下是需要執行的N個操作。除了回車符之外,輸入文件的所有字符的ASCII碼都在閉區間[32, 126]內。且行尾沒有空格。
Output
依次對應輸入文件中每條GET指令的輸出,不得有任何多餘的字符。
Sample Input
Insert 13
Balanced eert
Move 2
Delete 5
Next
Insert 7
editor
Move 0
Get
Move 11
Rotate 4
Get
Sample Output
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
#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();
}
}