【splay】BZOJ 1507:[NOI2003]Editor

BZOJ 1507:[NOI2003]Editor


Description

Input

输入文件editor.in的第一行是指令条数t,以下是需要执行的t个操作。


Output

输出文件editor.out的每行依次对应输入文件中每条GET指令的输出。


Sample Input

15
Insert 26
abcdefghijklmnop
qrstuv wxy
Move 15
Delete 11
Move 5
Insert 1
^
Next
Insert 1
_
Next
Next
Insert 4
.\/.
Get 4
Prev
Insert 1
^
Move 0
Get 22


Sample Output

.\/.
abcde^_^f.\/.ghijklmno


HINT

为了使输入文件便于阅读,Insert操作的字符串中可能会插入一些回车符,请忽略掉它们(如果难以理解这句话,可以参考样例)。 除了回车符之外,输入文件的所有字符的ASCII码都在闭区间[32, 126]内。且行尾没有空格。 这里我们有如下假定:  MOVE操作不超过50000个,INSERT和DELETE操作的总个数不超过4000,PREV和NEXT操作的总个数不超过200000。  所有INSERT插入的字符数之和不超过2M(1M=1024*1024),正确的输出文件长度不超过3M字节。  DELETE操作和GET操作执行时光标后必然有足够的字符。MOVE、PREV、NEXT操作必然不会试图把光标移动到非法位置。  输入文件没有错误。 对C++选手的提示:经测试,最大的测试数据使用fstream进行输入有可能会比使用stdio慢约1秒。


Solution

普通的序列splay…
不过要加一个变量pos记录光标的位置
其它没什么好说的了..
记得空间开大一点…

Code

#include
#include
#include
#include

using namespace std;

#define maxn 2200233

char s[23];

struct splay{
    int ch[2],fa,size;
    char v;
}t[maxn];

int root,size=2;

inline void update(int k){t[k].size=t[t[k].ch[1]].size+t[t[k].ch[0]].size+1;}

inline int in()
{
    int x=0;char ch=getchar();
    while(ch<'0'||ch>'9')ch=getchar();
    while(ch<='9'&&ch>='0')x=x*10+ch-'0',ch=getchar();
    return x;
}

void rotate(int x,int &k,int d)
{
    int y,z;
    y=t[x].fa;z=t[y].fa;
    if(y==k)k=x;
    else {if(t[z].ch[0]==y)t[z].ch[0]=x;else t[z].ch[1]=x;}
    t[x].fa=z,t[y].fa=x,t[t[x].ch[d]].fa=y;
    t[y].ch[d^1]=t[x].ch[d],t[x].ch[d]=y;
    update(y),update(x);
}

void splay(int x,int &k)
{
    int y,z;
    while(x!=k)
    {
        y=t[x].fa,z=t[y].fa;
        if(y!=k)
        {
            if(t[y].ch[0]==x&&t[z].ch[0]==y)rotate(y,k,1);
            else if(t[y].ch[1]==x&&t[z].ch[1]==y)rotate(y,k,0);
            else if(t[y].ch[0]==x&&t[z].ch[1]==y)rotate(x,k,1);
            else if(t[y].ch[1]==x&&t[z].ch[0]==y)rotate(x,k,0);
        }
        if(t[t[x].fa].ch[0]==x)rotate(x,k,1);
        else rotate(x,k,0);
    }
}

int find(int k,int x)
{
    if(t[t[k].ch[0]].size>=x)return find(t[k].ch[0],x);
    else if(t[t[k].ch[0]].size+1return find(t[k].ch[1],x-1-t[t[k].ch[0]].size);
    else return k;
}

void print(int rt)
{
    if(t[rt].ch[0])print(t[rt].ch[0]);
    printf("%c",t[rt].v);
    if(t[rt].ch[1])print(t[rt].ch[1]);
}

int main()
{
    freopen("1507.in","r",stdin);
    int n,pos=1;
    scanf("%d",&n);
    t[1].ch[1]=2;t[2].fa=1;t[1].size=2,t[2].size=1;root=1;
    for(int i=1;i<=n;i++)
    {
        int x,tot,now,ans1,ans2;
        char ch;
        scanf("%s",s);
        if(s[0]=='I')
        {
            ans1=find(root,pos);
            ans2=find(root,pos+1);
            splay(ans1,root);
            splay(ans2,t[root].ch[1]);
            x=in();
            tot=0;now=ans2;
            while(tot!=x)
            {
                ch=getchar();
                if(ch!='\n')
                {
                    size++;
                    t[size].size=x-tot;t[size].fa=now;t[size].v=ch;
                    if(now==ans2)t[now].ch[0]=size;
                    else t[now].ch[1]=size;
                    now=size;
                    tot++;
                }
            }
            update(ans2);update(ans1);
        }
        else if(s[0]=='M')
        {
            pos=in()+1;
        }
        else if(s[0]=='D')
        {
            x=in();
            ans1=find(root,pos);
            ans2=find(root,pos+x+1);
            splay(ans1,root);
            splay(ans2,t[root].ch[1]);
            t[ans2].size-=x;t[ans2].ch[0]=0;
            update(ans1);
        }
        else if(s[0]=='G')
        {
            x=in();
            ans1=find(root,pos);
            ans2=find(root,pos+x+1);
            splay(ans1,root);
            splay(ans2,t[root].ch[1]);
            print(t[ans2].ch[0]);
            printf("\n");
        }
        else if(s[0]=='P')
        {
            pos--;
        }
        else if(s[0]=='N')
        {
            pos++;
        }
    }
}

你可能感兴趣的:(splay,数据结构)