zoukankan      html  css  js  c++  java
  • BZOJ1269: [AHOI2006]文本编辑器editor

    BZOJ1269: [AHOI2006]文本编辑器editor

    Description

    这些日子,可可不和卡卡一起玩了,原来可可正废寝忘食的想做一个简单而高效的文本编辑器。

    你能帮助他吗?为了明确任务目标,可可对“文本编辑器”做了一个抽象的定义:

       

    文本:由0个或多个字符构成的序列。

    这些字符的ASCII码在闭区间[32, 126]内,也就是说,这些字符均为可见字符或空格。

    光标:在一段文本中用于指示位置的标记,可以位于文本的第一个字符之前,文本的最后一个字符之后或文本的某两个相邻字符之间。

    文本编辑器:为一个可以对一段文本和该文本中的一个光标进行如下七条操作的程序。

    如果这段文本为空,我们就说这个文本编辑器是空的。

    编写一个程序:

     建立一个空的文本编辑器。

     从输入文件中读入一些操作指令并执行。

     对所有执行过的GET操作,将指定的内容写入输出文件。

    Input

    输入文件中第一行是指令条数N,以下是需要执行的N个操作。

    除了回车符之外,输入文件的所有字符的ASCII码都在闭区间[32, 126]内。且行尾没有空格。

    Output

    依次对应输入文件中每条GET指令的输出,不得有任何多余的字符。

    Sample Input

    10
    Insert 13
    Balanced eert
    Move 2
    Delete 5
    Next
    Insert 7
    editor
    Move 0
    Get
    Move 11
    Rotate 4
    Get

    Sample Output

    B
    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操作不会把光标移动到非法位置。

     输入文件没有错误。

    题解Here!

    区间神器——Splay!

    其实可以看看这题:BZOJ1500: [NOI2005]维修数列

    只不过字符串处理比较烦。。。

    附代码:

    #include<iostream>
    #include<algorithm>
    #include<cstdio>
    #include<cstring>
    #include<string>
    #include<queue>
    #define MAXN 3000010
    using namespace std;
    queue<int> point;
    int mouse=0,root=0,size=0;
    char val[MAXN];
    struct node{
        int f,s,flag,son[2];
        char v;
    }a[MAXN];
    inline int read(){
        int date=0,w=1;char c=0;
        while(c<'0'||c>'9'){if(c=='-')w=-1;c=getchar();}
        while(c>='0'&&c<='9'){date=date*10+c-'0';c=getchar();}
        return date*w;
    }
    inline void clean(int rt){
        a[rt].son[0]=a[rt].son[1]=a[rt].f=a[rt].s=a[rt].flag=a[rt].v=0;
    }
    inline void pushup(int rt){
        if(!rt)return;
        a[rt].s=1;
        if(a[rt].son[0])a[rt].s+=a[a[rt].son[0]].s;
        if(a[rt].son[1])a[rt].s+=a[a[rt].son[1]].s;
    }
    inline void pushdown(int rt){
        if(!rt||!a[rt].flag)return;
        if(a[rt].son[0]){
            a[a[rt].son[0]].flag^=1;
            swap(a[a[rt].son[0]].son[0],a[a[rt].son[0]].son[1]);
        }
        if(a[rt].son[1]){
            a[a[rt].son[1]].flag^=1;
            swap(a[a[rt].son[1]].son[0],a[a[rt].son[1]].son[1]);
        }
        a[rt].flag^=1;
    }
    inline void turn(int rt,int k){
        int x=a[rt].f,y=a[x].f;
        a[x].son[k^1]=a[rt].son[k];
        if(a[rt].son[k])a[a[rt].son[k]].f=x;
        a[rt].f=y;
        if(y)a[y].son[a[y].son[1]==x]=rt;
        a[x].f=rt;
        a[rt].son[k]=x;
        pushup(x);pushup(rt);
    }
    void splay(int rt,int ancestry){
        while(a[rt].f!=ancestry){
            int x=a[rt].f,y=a[x].f;
            if(y==ancestry)turn(rt,a[x].son[0]==rt);
            else{
                int k=a[y].son[0]==x?1:0;
                if(a[x].son[k]==rt){turn(rt,k^1);turn(rt,k);}
                else{turn(x,k);turn(rt,k);}
            }
        }
        if(ancestry==0)root=rt;
    }
    inline int newnode(char c){
        int rt;
        if(point.empty())rt=++size;
        else{
        	rt=point.front();
        	point.pop();
        }
        a[rt].son[0]=a[rt].son[1]=0;
        a[rt].v=c;a[rt].s=1;a[rt].flag=0;
        return rt;
    }
    int buildtree(int l,int r){
        if(l>r)return 0;
        int mid=l+r>>1,lson=0,rson=0;
        lson=buildtree(l,mid-1);
        int rt=newnode(val[mid]);
        rson=buildtree(mid+1,r);
        a[rt].son[0]=lson;
        a[rt].son[1]=rson;
        if(lson)a[lson].f=rt;
        if(rson)a[rson].f=rt;
        pushup(rt);
        return rt;
    }
    int kth(int rt,int k){
        if(a[rt].s<k)return 0;
        while(1){
        	pushdown(rt);
            int y=a[rt].son[0];
            if(k>a[y].s+1){
                k-=a[y].s+1;
                rt=a[rt].son[1];
            }
            else if(k<=a[y].s)rt=y;
            else return rt;
        }
    }
    inline void insert(int rt,int k){
        int front=kth(rt,mouse+1),next=kth(rt,mouse+2),q=buildtree(1,k);
        splay(front,0);splay(next,front);
        a[next].son[0]=q;a[q].f=next;
        pushup(next);pushup(front);
    }
    void delete_tree(int rt){
        if(!rt)return;
        point.push(rt);
        if(a[rt].son[0])delete_tree(a[rt].son[0]);
        if(a[rt].son[1])delete_tree(a[rt].son[1]);
        clean(rt);
    }
    inline void remove(int rt,int k){
        int front=kth(rt,mouse+1),next=kth(rt,mouse+k+2),q;
        splay(front,0);splay(next,front);
        q=a[next].son[0];
        delete_tree(q);
        a[next].son[0]=0;
        pushup(next);pushup(front);
    }
    inline void get(int rt,int k){
        int front=kth(rt,mouse+1),next=kth(rt,mouse+k+2),q;
        splay(front,0);splay(next,front);
        q=a[next].son[0];
        if(a[q].v!=0)printf("%c",a[q].v);
        printf("
    ");
    }
    inline void reverse(int rt,int k){
        int front=kth(rt,mouse+1),next=kth(rt,mouse+k+2),q;
        splay(front,0);splay(next,front);
        q=a[next].son[0];
        a[q].flag^=1;
        swap(a[q].son[0],a[q].son[1]);
    }
    void work(){
        int x,y,k,t=read();
        char ch[10];
        while(t--){
            scanf("%s",ch);
            switch(ch[0]){
                case 'M':mouse=read();break;
                case 'I':{
                    k=read();
                    for(int j=1;j<=k;j++){
                    	char c=getchar();
                    	while(c=='
    '||c=='
    ')c=getchar();
                    	val[j]=c;
                    }
                    insert(root,k);
                    break;
                }
                case 'D':{
                	k=read();
                	remove(root,k);
                    break;
                }
                case 'G':{
                	k=1;
                	get(root,k);
                    break;
                }
                case 'R':{
                	k=read();
                	reverse(root,k);
                	break;
                }
                case 'P':mouse--;break;
                case 'N':mouse++;break;
            }
        }
    }
    void init(){
        val[1]=val[2]=0;
        root=buildtree(1,2);
    }
    int main(){
        init();
        work();
        return 0;
    }
    

    $Update ext{于}2019.3.17$:

    终于在洛谷上过了。。。

    洛谷上的官方数据有毒。。。

    总结起来就是:

    1. 会有多余的操作:如果第一个字母与给定操作都不匹配的话,忽略即可。
    2. 读入INSERT的字符串的时候,读完数字$n$之后的下一行,连续读$n$个字符即为给定字符串。也就是说,回车符也算字符。
    3. 输出的时候,如果输出字符本身就是回车符,不必再输出换行符,否则输出换行符。

    可见出题人有多么的不负责任。。。

    附代码:

    #include<iostream>
    #include<algorithm>
    #include<cstdio>
    #include<queue>
    #define MAXN 3000010
    using namespace std;
    queue<int> point;
    int mouse=0,root=0,size=0;
    char val[MAXN];
    struct node{
        int f,s,flag,son[2];
        char v;
    }a[MAXN];
    inline int read(){
        int date=0,w=1;char c=0;
        while(c<'0'||c>'9'){if(c=='-')w=-1;c=getchar();}
        while(c>='0'&&c<='9'){date=date*10+c-'0';c=getchar();}
        return date*w;
    }
    inline void clean(int rt){
        a[rt].son[0]=a[rt].son[1]=a[rt].f=a[rt].s=a[rt].flag=a[rt].v=0;
    }
    inline void pushup(int rt){
        if(!rt)return;
        a[rt].s=1;
        if(a[rt].son[0])a[rt].s+=a[a[rt].son[0]].s;
        if(a[rt].son[1])a[rt].s+=a[a[rt].son[1]].s;
    }
    inline void pushdown(int rt){
        if(!rt||!a[rt].flag)return;
        if(a[rt].son[0]){
            a[a[rt].son[0]].flag^=1;
            swap(a[a[rt].son[0]].son[0],a[a[rt].son[0]].son[1]);
        }
        if(a[rt].son[1]){
            a[a[rt].son[1]].flag^=1;
            swap(a[a[rt].son[1]].son[0],a[a[rt].son[1]].son[1]);
        }
        a[rt].flag^=1;
    }
    inline void turn(int rt,int k){
        int x=a[rt].f,y=a[x].f;
        a[x].son[k^1]=a[rt].son[k];
        if(a[rt].son[k])a[a[rt].son[k]].f=x;
        a[rt].f=y;
        if(y)a[y].son[a[y].son[1]==x]=rt;
        a[x].f=rt;
        a[rt].son[k]=x;
        pushup(x);pushup(rt);
    }
    void splay(int rt,int ancestry){
        while(a[rt].f!=ancestry){
            int x=a[rt].f,y=a[x].f;
            if(y==ancestry)turn(rt,a[x].son[0]==rt);
            else{
                int k=a[y].son[0]==x?1:0;
                if(a[x].son[k]==rt){turn(rt,k^1);turn(rt,k);}
                else{turn(x,k);turn(rt,k);}
            }
        }
        if(ancestry==0)root=rt;
    }
    inline int newnode(char c){
        int rt;
        if(point.empty())rt=++size;
        else{
        	rt=point.front();
        	point.pop();
        }
        a[rt].son[0]=a[rt].son[1]=0;
        a[rt].v=c;a[rt].s=1;a[rt].flag=0;
        return rt;
    }
    int buildtree(int l,int r){
        if(l>r)return 0;
        int mid=l+r>>1,lson=0,rson=0;
        lson=buildtree(l,mid-1);
        int rt=newnode(val[mid]);
        rson=buildtree(mid+1,r);
        a[rt].son[0]=lson;
        a[rt].son[1]=rson;
        if(lson)a[lson].f=rt;
        if(rson)a[rson].f=rt;
        pushup(rt);
        return rt;
    }
    int kth(int rt,int k){
        if(a[rt].s<k)return 0;
        while(1){
        	pushdown(rt);
            int y=a[rt].son[0];
            if(k>a[y].s+1){
                k-=a[y].s+1;
                rt=a[rt].son[1];
            }
            else if(k<=a[y].s)rt=y;
            else return rt;
        }
    }
    inline void insert(int rt,int k){
        int front=kth(rt,mouse+1),next=kth(rt,mouse+2),q=buildtree(1,k);
        splay(front,0);splay(next,front);
        a[next].son[0]=q;a[q].f=next;
        pushup(next);pushup(front);
    }
    void delete_tree(int rt){
        if(!rt)return;
        point.push(rt);
        if(a[rt].son[0])delete_tree(a[rt].son[0]);
        if(a[rt].son[1])delete_tree(a[rt].son[1]);
        clean(rt);
    }
    inline void remove(int rt,int k){
        int front=kth(rt,mouse+1),next=kth(rt,mouse+k+2),q;
        splay(front,0);splay(next,front);
        q=a[next].son[0];
        delete_tree(q);
        a[next].son[0]=0;
        pushup(next);pushup(front);
    }
    inline void get(int rt,int k){
        int front=kth(rt,mouse+1),next=kth(rt,mouse+k+2),q;
        splay(front,0);splay(next,front);
        q=a[next].son[0];
        if(a[q].v!=0&&a[q].v!='
    ')printf("%c",a[q].v);
        printf("
    ");
    }
    inline void reverse(int rt,int k){
        int front=kth(rt,mouse+1),next=kth(rt,mouse+k+2),q;
        splay(front,0);splay(next,front);
        q=a[next].son[0];
        a[q].flag^=1;
        swap(a[q].son[0],a[q].son[1]);
    }
    void work(){
        int k,t=read();
        char ch[10];
        while(t--){
            scanf("%s",ch);
            switch(ch[0]){
                case 'M':mouse=read();break;
                case 'I':{
                    k=read();
                    for(int j=1;j<=k;j++)val[j]=getchar();
                    insert(root,k);
                    break;
                }
                case 'D':{
                	k=read();
                	remove(root,k);
                    break;
                }
                case 'G':{
                	k=1;
                	get(root,k);
                    break;
                }
                case 'R':{
                	k=read();
                	reverse(root,k);
                	break;
                }
                case 'P':mouse--;break;
                case 'N':mouse++;break;
                default:break;
            }
        }
    }
    void init(){
        val[1]=val[2]=0;
        root=buildtree(1,2);
    }
    int main(){
        init();
        work();
        return 0;
    }
    
  • 相关阅读:
    可爱的中国电信 请问我们的电脑还属于我们自己吗?
    了解客户的需求,写出的代码或许才是最优秀的............
    DELPHI DATASNAP 入门操作(3)简单的主从表的简单更新【含简单事务处理】
    用数组公式获取字符在字符串中最后出现的位置
    在ehlib的DBGridEh控件中使用过滤功能(可以不用 MemTableEh 控件 适用ehlib 5.2 ehlib 5.3)
    格式化json返回的时间
    ExtJs中使用Ajax赋值给全局变量异常解决方案
    java compiler level does not match the version of the installed java project facet (转)
    收集的资料(六)ASP.NET编程中的十大技巧
    收集的资料共享出来(五)Asp.Net 权限解决办法
  • 原文地址:https://www.cnblogs.com/Yangrui-Blog/p/9388377.html
Copyright © 2011-2022 走看看