• bzoj1269 文本编辑器 splay


    直接搞棵splay就行了,不要把光标弄到树中而是把光标当成询问或操作区间的端点标志这样会简单很多。

    7点40分写到9点20分,包括调试总共花了一个小时40分钟,这次是自己独立调出来的,总算对splay有一定的了解。

    设计操作:区间翻转,区间删除和插入,取第k个数。

    这里的区间插入不是一个一个插,那样会很容易使树退化成链状,这里应该直接在key_val中build。

    #include<bits/stdc++.h>
    #define REP(i,a,b) for(int i=a;i<=b;i++)
    #define MS0(a) memset(a,0,sizeof(a))
    #define key_val ch[ch[rt][1]][0]
    
    using namespace std;
    
    typedef long long ll;
    const int INF=1e9+10;
    const int maxn=2000100;
    
    int N;
    char op[20];int k;
    char str[maxn];
    int pos;
    
    int pre[maxn],sz[maxn],ch[maxn][2],rt,tot1;
    int s[maxn],tot2;
    char val[maxn];
    int rev[maxn];
    
    void debug(int r)
    {
        if(r==0) return;
        debug(ch[r][0]);
        printf("%c",val[r]);
        //printf("lch=%2d rch=%2d pre=%2d r=%2d val=%c sz=%2d rt=%2d
    ",ch[r][0],ch[r][1],pre[r],r,val[r],sz[r],rt);
        debug(ch[r][1]);
    }
    
    void up(int r)
    {
        sz[r]=sz[ch[r][0]]+sz[ch[r][1]]+1;
    }
    
    void update_rev(int r)
    {
        if(!r) return;
        swap(ch[r][0],ch[r][1]);
        rev[r]^=1;
    }
    
    void down(int r)
    {
        if(rev[r]){
            update_rev(ch[r][0]);
            update_rev(ch[r][1]);
            rev[r]=0;
        }
    }
    
    void newnode(int &r,int fa,char k)
    {
        if(tot2) r=s[tot2--];
        else r=++tot1;
        pre[r]=fa;val[r]=k;
        sz[r]=1;rev[r]=0;MS0(ch[r]);
    }
    
    void rot(int x,int kind)
    {
        int y=pre[x];
        down(y);down(x);
        ch[y][kind^1]=ch[x][kind];
        pre[ch[x][kind]]=y;
        if(pre[y]) ch[pre[y]][ch[pre[y]][1]==y]=x;
        pre[x]=pre[y];
        ch[x][kind]=y;
        pre[y]=x;
        up(y);
    }
    
    void splay(int x,int goal)
    {
        down(x);
        while(pre[x]!=goal){
            if(pre[pre[x]]==goal) rot(x,ch[pre[x]][0]==x);
            else{
                int y=pre[x],z=pre[y];
                int kind=ch[y][0]==x,one=0;
                if(ch[y][0]==x&&ch[z][0]==y) one=1;
                if(ch[y][1]==x&&ch[z][1]==y) one=1;
                if(one) rot(y,kind),rot(x,kind);
                else rot(x,kind),rot(x,kind^1);
            }
        }
        if(goal==0) rt=x;
        up(x);
    }
    
    void rto(int k,int goal)
    {
        int r=rt;k++;
        while(k!=sz[ch[r][0]]+1){
            down(r);
            if(k<sz[ch[r][0]]+1) r=ch[r][0];
            else k-=sz[ch[r][0]]+1,r=ch[r][1];
        }
        splay(r,goal);
    }
    
    void Rev(int l,int r)
    {
        rto(l-1,0);
        rto(r+1,rt);
        down(rt);down(ch[rt][1]);
        update_rev(key_val);
        up(ch[rt][1]);up(rt);
    }
    
    void Del(int l,int r)
    {
        rto(l-1,0);
        rto(r+1,rt);
        down(rt);down(ch[rt][1]);
        key_val=0;
        up(ch[rt][1]);up(rt);
    }
    
    void build(int &x,int l,int r,int fa)
    {
        if(l>r) return;
        int m=(l+r)>>1;
        //cout<<"l="<<l<<" r="<<r<<" m="<<m<<" str="<<str<<endl;
        newnode(x,fa,str[m]);
        build(ch[x][0],l,m-1,x);
        build(ch[x][1],m+1,r,x);
        up(x);
    }
    
    void Insert()
    {
        rto(pos,0);
        rto(pos+1,rt);
        down(rt);down(ch[rt][1]);
        int n=strlen(str);
        build(key_val,0,n-1,ch[rt][1]);
        pre[key_val]=ch[rt][1];
        up(ch[rt][1]);up(rt);
    }
    
    char Get(int k)
    {
        int r=rt;k++;
        while(k!=sz[ch[r][0]]+1){
            down(r);
            if(k<sz[ch[r][0]]+1) r=ch[r][0];
            else k-=sz[ch[r][0]]+1,r=ch[r][1];
        }
        return val[r];
    }
    
    void Init()
    {
        pre[0]=sz[0]=ch[0][0]=ch[0][1]=rev[0]=0;
        rt=tot1=tot2=0;
        newnode(rt,0,'-');
        newnode(ch[rt][1],rt,'+');
        sz[rt]=2;
    }
    
    int main()
    {
        freopen("in.txt","r",stdin);
        while(cin>>N){
            Init();
            pos=0;
            REP(i,1,N){
                scanf("%s",op);
                if(op[0]=='I'){
                    scanf("%d",&k);
                    gets(str);gets(str);
                    Insert();
                }
                else if(op[0]=='M'){
                    scanf("%d",&k);
                    pos=k;
                }
                else if(op[0]=='D'){
                    scanf("%d",&k);
                    Del(pos+1,pos+k);
                }
                else if(op[0]=='R'){
                    scanf("%d",&k);
                    Rev(pos+1,pos+k);
                }
                else if(op[0]=='G') printf("%c
    ",Get(pos+1));
                else if(op[0]=='P') pos--;
                else pos++;
            }
        }
        return 0;
    }
    View Code
    没有AC不了的题,只有不努力的ACMER!
  • 相关阅读:
    返回表对象的方法之一--bulk collect into
    coolite 获取新的页面链接到当前页面指定位置Panel的运用
    oracle 当前年到指定年的年度范围求取
    JAVA WEB 过滤器
    Java复习笔记(二):数据类型以及逻辑结构
    Java复习笔记(一):概念解释和运行步骤
    装饰器理解
    Flask大型项目框架结构理解
    JSP内置对象(一)
    Java Web第一个应用搭建
  • 原文地址:https://www.cnblogs.com/--560/p/5202694.html
Copyright © 2020-2023  润新知