您的位置:首页 > 其它

BZOJ 1269 文本编辑器editor(splay)

2013-12-04 18:28 218 查看
题目链接: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
,R
,f
,s
,isRev
;
char k
;

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
,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;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: