zoukankan      html  css  js  c++  java
  • [cogs2314][HZOI 2015] Persistable Editor

    [cogs2314][HZOI 2015]Persistable Editor - 可持久化平衡树

    题目链接

    首先吐槽扯淡几句

    【题目描述】

    维护一种可持久化的文本编辑器,支持下列操作:
    1 p str 在当前版本的第p个字符后插入字符串str,并作为下一版本(数据保证0<=p<=当前字符串的长度,且插入的字符串中只有小写字母)
    2 p c 在当前版本中删除从第p个字符开始的后c个字符,并作为下一版本(包含第p个字符,数据保证1<=p<=当前字符串的长度,且p+c-1<=当前字符串的长度)
    3 x p c 输出第x个版本从第p个字符开始的后c个字符(包含第p个字符,数据保证1<=p<=第x个版本的字符串的长度,且p+c-1<=第x个版本的字符串的长度)
    为了体现在线,你需要维护一个变量d,在3操作之后,d加上你输出字符串中字符'c'的数量,并且在数据中给出的操作1中的p,操作2中的p和c,操作3中的x,p,c均为加上变量d的结果,你需要把它们减去d之后运算
    开始时为空串,d=0,且为版本0,每进行操作1,2就会以上一版本的基础上修改形成下一版本

    【输入格式】

    第一行一个数n,表示有n个操作
    下面n行,第一个数字为op,表示操作类型
    op=1时表示第一种操作,后面有一个数p和一个字符串str,意义同上面的描述,在操作之前,你需要将p减去d,才能得到正确的p,d的意义同上面的描述,表示你之前第三种操作输出的所有字符串中字符'c'的数量
    op=2时表示第二种操作,后面有两个数p,c,意义同上面的描述,在操作之前,你需要将p和c减去d,才能得到正确的p和c,d的意义同上面的描述,表示你之前第三种操作输出的所有字符串中字符'c'的数量
    op=3时表示第三种操作,后面有三个数x,p,c,意义同上面的描述,在操作之前,你需要将x,p和c减去d,才能得到正确的x,p和c,d的意义同上面的描述,表示你之前第三种操作输出的所有字符串中字符'c'的数量

    【输出格式】

    对于每个第三种操作输出一行表示结果

    【样例输入】

    6
    1 0 abcdefgh
    2 4 3
    3 1 2 5
    3 3 3 4
    1 4 xy
    3 5 4 6
    

    【样例输出】

    bcdef
    bcg
    bxyc
    

    【提示】

    对于样例解密的结果为

    6
    1 0 abcdefgh
    2 4 3
    3 1 2 5
    3 2 2 3
    1 2 xy
    3 3 2 4
    

    本题共20组测试数据,一个点5分,给出数据特征如下
    被我吞啦

    【来源】

    by stdafx
    ps:题目异常丑陋,凑合看吧,我只是想普及下rope和可持久化平衡树
    pps:数据真难造,比标算还难写

    题解

    可持久化平衡树。。。看了XXX博客然后1A了并不感动。。。
    其实还好啊。。。。
    就是每次修改到一个节点时先复制一份副本。。。

    il vd copy(point&a,point b){
        if(b==null)a=null;
        else a=new node('%'),*a=*b;
    }
    

    所以修改一下split和merge。。。

    il vd merge(point&rt,point a,point b){
        if(a==null)copy(rt,b);
        else if(b==null)copy(rt,a);
        else if(a->rand<b->rand)copy(rt,a),merge(rt->rs,a->rs,b),rt->reset();
        else copy(rt,b),merge(rt->ls,a,b->ls),rt->reset();
    }
    il vd split(point rt,point&a,point&b,int num){
        if(!num)copy(b,rt),a=null;
        else if(rt->size<=num)copy(a,rt),b=null;
        else if(num<=rt->ls->size)copy(b,rt),split(rt->ls,a,b->ls,num),b->reset();
        else copy(a,rt),split(rt->rs,a->rs,b,num-rt->ls->size-1),a->reset();
    }
    

    然后弄一个root数组记录所有的树根。。。
    剩下的和普通平衡树一毛一样。。。

    // It is made by XZZ
    #include<cstdio>
    #include<algorithm>
    #include<cstring>
    #define Fname "persistable_editor"
    using namespace std;
    #define rep(a,b,c) for(rg int a=b;a<=c;a++)
    #define drep(a,b,c) for(rg int a=b;a>=c;a--)
    #define erep(a,b) for(rg int a=fir[b];a;a=nxt[a])
    #define il inline
    #define rg register
    #define vd void
    typedef long long ll;
    il int gi(){
        rg int x=0,f=1;rg char ch=getchar();
        while(ch<'0'||ch>'9')f=ch=='-'?-1:f,ch=getchar();  
        while(ch>='0'&&ch<='9')x=x*10+ch-'0',ch=getchar();
        return x*f;
    }
    int d=0,cnt=0,seed=151806;
    il int Rand(){return seed=seed*19260817ll%2147483647;}
    typedef struct node* point;
    point null;
    struct node{
        char data;
        int rand,size;
        point ls,rs;
        node(char _data){data=_data,rand=Rand(),size=1,ls=rs=null;}
        il vd reset(){size=ls->size+rs->size+1;}
    };
    point root[100101];
    il vd copy(point&a,point b){
        if(b==null)a=null;
        else a=new node('%'),*a=*b;
    }
    il vd merge(point&rt,point a,point b){
        if(a==null)copy(rt,b);
        else if(b==null)copy(rt,a);
        else if(a->rand<b->rand)copy(rt,a),merge(rt->rs,a->rs,b),rt->reset();
        else copy(rt,b),merge(rt->ls,a,b->ls),rt->reset();
    }
    il vd split(point rt,point&a,point&b,int num){
        if(!num)copy(b,rt),a=null;
        else if(rt->size<=num)copy(a,rt),b=null;
        else if(num<=rt->ls->size)copy(b,rt),split(rt->ls,a,b->ls,num),b->reset();
        else copy(a,rt),split(rt->rs,a->rs,b,num-rt->ls->size-1),a->reset();
    }
    il point build(){
        char s[203];
        scanf("%s",s+1);
        int n=strlen(s+1);
        point stack[n+2];int top=0;
        rep(i,1,n){
    	point now=new node(s[i]),last=null;
    	while(top&&stack[top]->rand>now->rand)last=stack[top],stack[top--]->reset();
    	if(top)stack[top]->rs=now;now->ls=last,stack[++top]=now;
        }
        while(top)stack[top--]->reset();
        return stack[1];
    }
    il vd ins(){
        int p=gi()-d;
        point a,b;
        split(root[cnt],a,b,p);
        merge(a,a,build()),merge(root[++cnt],a,b);
    }
    il vd del(){
        int p=gi()-d,tot=gi()-d;
        point a,b,c;
        split(root[cnt],a,b,p-1),split(b,b,c,tot);
        merge(root[++cnt],a,c);
    }
    il vd dfs(point now){
        if(now->data=='c')++d;
        if(now!=null)dfs(now->ls),putchar(now->data),dfs(now->rs);
    }
    il vd prt(){
        int x=gi()-d,p=gi()-d,tot=gi()-d;
        point a,b,c;
        split(root[x],a,b,p-1),split(b,b,c,tot);
        dfs(b),puts("");
        merge(a,a,b),merge(root[x],a,c);
    }
    int main(){
        freopen(Fname".in","r",stdin);
        freopen(Fname".out","w",stdout);
        int n=gi(),opt;
        null=new node('%');
        null->size=0;
        rep(i,0,n)root[i]=null;
        while(n--){
    	opt=gi();
    	if(opt==1)ins();
    	if(opt==2)del();
    	if(opt==3)prt();
        }
        return 0;
    }
    

    所以我1A了好感动。。。

    最后扯淡几句

    我竟然上榜了。。。

  • 相关阅读:
    编写一个程序的步骤
    vue实现瀑布流
    Vue 解决动态生成列表点击事件无效的问题
    筛选分类列表展示
    php实现类似慕课网,php中文网的分类功能
    在一个页面修改数据,并且ajax刷新数据列表的数据实现。
    记账小程序系统简单规划
    茶叶项目---产品的规格添加
    茶叶商城开发
    后端图片上传
  • 原文地址:https://www.cnblogs.com/xzz_233/p/7382427.html
Copyright © 2011-2022 走看看