BZOJ1507 [NOI2003]Editor

AC通道:http://www.lydsy.com/JudgeOnline/problem.php?id=1507

【分析】

  据说打完维修数列,什么数据结构题都是浮云了...这题似乎就是一个简化版咯。

  这题的要求都和字母的值无关,而是与字母在序列中的位置有关...所以应当用位置关系建树的方法啦[就是每次找第k个位置就是这个节点的左边有k-1个节点]

  首先预处理出两个虚拟节点作为开头和结尾[这个也是区间操作的比较基础的哦...]。

  每次的添加就是找到光标和光标的下一个组成的区间,然后接在下一个的左子树上[联系之前的区间的做法...]

  删除就是找到要删除的区间就好了...不过维修数列的心理阴影...我还是将节点回收了一下[会慢些...]。

  输出的话也是找到区间然后输出中序遍历。

  对于光标的操作直接设一个全局变量作为光标位置就好。

  

  本题有一个坑点...就是“所有INSERT插入的字符数之和不超过2M(1M=1024*1024)”很可能一个INSERT就输进来2000000个字符哦....所以要开这么大。

  [不过笔者偷偷瞄了数据只有1500000...]

#include<cstdio>
#include<cstring>
#include<algorithm>

using namespace std;

const int maxn=1500010;

struct Node{
    int ch[2],f;
    int sz;
    char cc;
}s[maxn];

int n,gb,rt;
int tb[maxn],cot2,cot1;
char ord[15],ch[maxn];

void update(int x){
    s[x].sz=s[s[x].ch[0]].sz+s[s[x].ch[1]].sz+1;
}

void Rotate(int x,int k){
    int y=s[x].f;s[x].f=s[y].f;
    if(s[y].f)    s[s[y].f].ch[y==s[s[y].f].ch[1]]=x;
    s[y].ch[k]=s[x].ch[k^1];
    if(s[x].ch[k^1]) s[s[x].ch[k^1]].f=y;
    s[y].f=x,s[x].ch[k^1]=y;
    update(y),update(x);
}

void Splay(int x,int gf){
    int y;
    while(s[x].f!=gf){
        y=s[x].f;
        if(s[y].f==gf) Rotate(x,x==s[y].ch[1]);
        else{int z=s[y].f;
            if(y==s[z].ch[0]){if(x==s[y].ch[0]) Rotate(y,0),Rotate(x,0);else Rotate(x,1),Rotate(x,0);}
            else {if(x==s[y].ch[1]) Rotate(y,1),Rotate(x,1);else Rotate(x,0),Rotate(x,1);}
        }
    }
    if(!gf) rt=x;
}

int Find(int k){
    int p=rt;
    while(p){
        if(k<=s[s[p].ch[0]].sz) p=s[p].ch[0];
        else{
            k-=s[s[p].ch[0]].sz;
            if(k==1) return p;
            k--;p=s[p].ch[1];
        }
    }
}

int New_Node(){
    int x;
    if(cot2) x=tb[cot2--];
    else x=++cot1;
    s[x].sz=1;
    s[x].ch[0]=s[x].ch[1]=0;
    return x;
}

int build(int l,int r){
    if(l>r) return 0;
    int mid=(l+r)>>1,x=New_Node();
    s[x].ch[0]=build(l,mid-1);
    s[x].ch[1]=build(mid+1,r);
    s[x].cc=ch[mid];
    if(s[x].ch[0]) s[s[x].ch[0]].f=x;
    if(s[x].ch[1]) s[s[x].ch[1]].f=x;
    update(x);
    return x;
}

void Del(int x){
    if(!x) return;tb[++cot2]=x;
    Del(s[x].ch[0]),Del(s[x].ch[1]);
}

void Print(int x){
    if(!x) return ;
    Print(s[x].ch[0]);
    if(s[x].cc)
        printf("%c",s[x].cc);
    Print(s[x].ch[1]);
}

int main(){
#ifndef ONLINE_JUDGE
    freopen("1507.in","r",stdin);
    freopen("1507.out","w",stdout);
#endif
    int x,k,t,t1;
    
    gb=rt=New_Node();
    s[rt].ch[1]=New_Node();
    s[2].f=rt;
    update(rt);
    
    scanf("%d",&n);
    while(n--){
        scanf("%s",ord);
        //Print(rt);putchar('\n');
        if(strcmp(ord,"Move")==0)
            scanf("%d",&x),gb=x+1;
        else if(strcmp(ord,"Insert")==0){
            scanf("%d",&x);
            for(int i=1;i<=x;i++){
                scanf("%c",&ch[i]);
                if(ch[i]=='\n') i--;
            }
            k=build(1,x);
            t=Find(gb);
            Splay(t,0);
            if(s[rt].ch[1]){
                t1=Find(gb+1);Splay(t1,rt);
                s[k].f=t1,s[t1].ch[0]=k;
                update(t1),update(rt);
            }
            else
                s[k].f=rt,s[rt].ch[1]=k,update(rt);
        }
        else if(strcmp(ord,"Delete")==0){
            scanf("%d",&x);
            t=Find(gb);t1=Find(gb+x+1);
            Splay(t,0),Splay(t1,t);
            Del(s[t1].ch[0]);
            s[t1].ch[0]=0;
            update(t1),update(t);
        }
        else if(strcmp(ord,"Get")==0){
            scanf("%d",&x);
            t=Find(gb),t1=Find(gb+x+1);
            Splay(t,0),Splay(t1,t);
            Print(s[t1].ch[0]);
            putchar('\n');
        }
        else if(strcmp(ord,"Prev")==0) gb--;
        else gb++;
    }
    
    return 0;
}
View Code

 

posted @ 2015-12-30 22:24  诚叙  阅读(339)  评论(0编辑  收藏  举报