BZOJ 1269 [AHOI2006]文本编辑器editor

本文介绍了一种使用Splay树实现的高效文本编辑器,能够执行包括插入、删除、反转等基本操作,并通过实例代码展示了如何处理这些操作。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

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


【题目分析】
Splay维护区间,但是加入了一些玄学元素。


【代码】(自己代码太丑了,贴一个学长的代码)

#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++;
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值