1 条题解

  • 1
    @ 2022-8-31 9:45:04
    #include<iostream>
    #include<cstdio>
    #include<cstring>
    using namespace std;
    unsigned int h[500000],pow[500000];
    char st[500000];
    int f[500000],n,l0[500000],r0[500000];
    void hs_make(char st[],unsigned int h[])
    {
        pow[0]=1;
        for(int i=1;i<=strlen(st);i++)h[i]=h[i-1]*233+st[i-1]-48,pow[i]=pow[i-1]*233;
    }
    unsigned int hs(int l,int r){return h[r]-h[l-1]*pow[r-l+1];}
    int xy(int l1,int r1,int l2,int r2)
    {
        if(r1-l1+1<r2-l2+1)return 1;
        if(r1-l1+1>r2-l2+1)return 0;
        int l=0,r=r1-l1+1,mid;
        while(l<r)
        {
            mid=(l+r+1)>>1;
            if(hs(l1,l1+mid-1)==hs(l2,l2+mid-1))l=mid;
            else r=mid-1;
        }
        return l!=r1-l1+1&&st[l1+l-1]<st[l2+l-1];//注意如果前缀就是整个字符串要特判
    }
    struct Segment_tree
    {
        int a[200000],tag[200000];
        void build(int rot,int lt,int rt)
        {
            tag[rot]=a[rot]=0;
            if(lt==rt)return;
            int mid=(lt+rt)>>1;
            build(rot<<1,lt,mid),build(rot<<1|1,mid+1,rt);
        }
        void pushdown(int rot,int lt,int rt)
        {
            if(tag[rot])
            {
                int t=tag[rot];tag[rot]=0;
                tag[rot<<1]=max(t,tag[rot<<1]),tag[rot<<1|1]=max(t,tag[rot<<1|1]);
                a[rot<<1]=max(t,a[rot<<1]),a[rot<<1|1]=max(t,a[rot<<1|1]);
            }
        }
        int query(int rot,int lt,int rt,int q)
        {
            if(lt==rt)return a[rot];
            int mid=(lt+rt)>>1;
            pushdown(rot,lt,rt);
            if(q<=mid)return query(rot<<1,lt,mid,q);
            else return query(rot<<1|1,mid+1,rt,q);
        }
        void update(int rot,int lt,int rt,int lq,int rq,int w)
        {
            if(lt>rq||rt<lq)return;
            if(lt>=lq&&rt<=rq)
            {
                a[rot]=max(a[rot],w),tag[rot]=max(tag[rot],w);
                return;
            }
            int mid=(lt+rt)>>1;
            pushdown(rot,lt,rt);
            update(rot<<1,lt,mid,lq,rq,w),update(rot<<1|1,mid+1,rt,lq,rq,w);
            a[rot]=max(a[rot<<1],a[rot<<1|1]);
        }
    }seg;//线段树
    int main()
    {
        while(scanf("%s",st)==1)
        {
            hs_make(st,h);n=strlen(st);
            for(int i=1;i<=n;i++)if(st[i-1]=='0')l0[i]=l0[i-1];else l0[i]=i;r0[n+1]=n+1;//端点特判
            for(int i=n;i>=1;i--)if(st[i-1]=='0')r0[i]=r0[i+1];else r0[i]=i;
    //		for(int i=1;i<=n;i++)cout<<l0[i]<<" "<<r0[i]<<endl;
            seg.build(1,0,n);
            for(int i=0;i<n;i++)
            {
                int fi=seg.query(1,0,n,i);
                int t=r0[i+1]+i-r0[fi];
                if(!xy(r0[fi],i,r0[i+1],t))t++;
    //			cout<<i<<" "<<fi<<" "<<t<<endl;
                if(t<=n)seg.update(1,0,n,t,n,i+1);
            }
    //		for(int i=1;i<=n;i++)cout<<f[i]<<" ";cout<<endl;
            int fn=seg.query(1,0,n,n);
            seg.build(1,0,n);//清树
            seg.update(1,0,n,l0[fn-1]+1,n,n);//先把前导零全都指向n
            for(int i=fn;i>1;i--)
            {
                int fi=seg.query(1,0,n,i);
                int t=l0[max(i-1+r0[i]-fi-1,0)]+1;//不可以是负数,特判
                if(!xy(r0[t],i-1,r0[i],fi))t=r0[t]+1;
    //			cout<<i<<" "<<f[i]<<" "<<t<<endl;
                seg.update(1,0,n,t,i-1,i-1);
            }
            int pos=seg.query(1,0,n,1);
            for(int i=1;i<=n;i++)
            {
                putchar(st[i-1]);//普通的输出
                if(i==pos&&i!=n)putchar(','),pos=seg.query(1,0,n,i+1);
            }
            putchar(10);
        }
    }
    
    • 1

    信息

    ID
    1234
    时间
    2000ms
    内存
    159MiB
    难度
    7
    标签
    递交数
    3
    已通过
    3
    上传者