题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=1269
题意:维护一个文本编辑器,初始时文本为空,光标在最开始位置也就是0.操作有以下:
思路:显然光标的移动是很简单的,只需要记录即可。那么剩下的操作实际还有四个:(设A为根,B为根右子树,C为B左子树)
(1)插入:插入位置在pos,只需要将pos调整到A,将pos+1调整到B,则其新的串插入C即可(当然插入的串要先建立一个子树);
(2)删除:设删除位置为pos,长度n,则删除区间实际是[pos+1,pos+n],则只需要将pos调整到A,pos+n+1调整到B,则C就是删除的区间;
(3)翻转:设翻转位置为pos,长度n,则翻转区间实际是[pos+1,pos+n],则只需要将pos调整到A,pos+n+1调整到B,则C就是翻转的区间,标记其翻转即可;
(4)查找第k个位置:节点记录一个本子树包含节点个数,则递归查找即可。
另外,对于区间的操作,为方便,在原串的两端分别增加一个元素更容易操作。
int tot,root,L[N],R[N],f[N],s[N],isRev[N];
char k[N];
inline void pushUp(int x)
{
if(x) s[x]=s[L[x]]+s[R[x]]+1;
}
inline void pushDown(int x)
{
if(!x) return;
if(isRev[x])
{
if(L[x]) isRev[L[x]]^=1;
if(R[x]) isRev[R[x]]^=1;
swap(L[x],R[x]);
isRev[x]=0;
}
}
inline void zig(int x)
{
int y=f[x],z=f[y];
if(z) L[z]==y?L[z]=x:R[z]=x;
f[x]=z;
L[y]=R[x];
if(R[x]) f[R[x]]=y;
R[x]=y;
f[y]=x;
pushUp(y);
pushUp(x);
if(root==y) root=x;
}
inline void zag(int x)
{
int y=f[x],z=f[y];
if(z) L[z]==y?L[z]=x:R[z]=x;
f[x]=z;
R[y]=L[x];
if(L[x]) f[L[x]]=y;
L[x]=y;
f[y]=x;
pushUp(y);
pushUp(x);
if(root==y) root=x;
}
inline void splay(int x,int goal)
{
int y;
while((y=f[x])!=goal)
{
if(f[y]!=goal)
{
pushDown(f[y]);
pushDown(y);
pushDown(x);
if(L[f[y]]==y) L[y]==x?(zig(y),zig(x)):(zag(x),zig(x));
else R[y]==x?(zag(y),zag(x)):(zig(x),zag(x));
}
else
{
pushDown(y);
pushDown(x);
L[y]==x?zig(x):zag(x);
}
}
}
int select(int k)
{
int x=root;
pushDown(x);
while(s[L[x]]+1!=k)
{
s[L[x]]>=k?x=L[x]:(k-=s[L[x]]+1,x=R[x]);
pushDown(x);
}
return x;
}
int newNode(char key,int p)
{
int e=++tot;
k[e]=key; f[e]=p; s[e]=1;
return e;
}
int buildTree(int left,int right,char str[],int p)
{
if(left>right) return 0;
int mid=(left+right)>>1;
int e=newNode(str[mid],p);
L[e]=buildTree(left,mid-1,str,e);
R[e]=buildTree(mid+1,right,str,e);
pushUp(e);
return e;
}
void insert(int pos,int n,char str[])
{
int x=select(pos+1),y=select(pos+2);
splay(x,0);
splay(y,x);
L[y]=buildTree(1,n,str,y);
splay(y,0);
}
void del(int pos,int n)
{
int x=select(pos+1),y=select(pos+1+n+1);
splay(x,0);
splay(y,x);
L[y]=0;
splay(y,0);
}
void reverse(int pos,int n)
{
int x=select(pos+1),y=select(pos+1+n+1);
splay(x,0);
splay(y,x);
isRev[L[y]]^=1;
}
void init()
{
root=newNode('$',0);
R[root]=newNode('$',root);
pushUp(root);
}
int n,curPos,x;
char str[N],op[20];
void getStr()
{
char c=getchar();
while(c!='\n') c=getchar();
gets(str+1);
}
int main()
{
init();RD(n);
while(n--)
{
RD(op);
if(op[0]=='M') RD(x),curPos=x;
else if(op[0]=='I') RD(x),getStr(),insert(curPos,x,str);
else if(op[0]=='D') RD(x),del(curPos,x);
else if(op[0]=='R') RD(x),reverse(curPos,x);
else if(op[0]=='G') putchar(k[select(curPos+2)]),puts("");
else if(op[0]=='P') curPos--;
else curPos++;
}
return 0;
}