• BZOJ 4592


    4592: [Shoi2015]脑洞治疗仪

    Time Limit: 20 Sec  Memory Limit: 256 MB
    Submit: 346  Solved: 147
    [Submit][Status][Discuss]

    Description

    曾经发明了自动刷题机的发明家SHTSC又公开了他的新发明:脑洞治疗仪--一种可以治疗他因为发明而日益增大的脑洞的神秘装置。
    为了简单起见,我们将大脑视作一个01序列。1代表这个位置的脑组织正常工作,0代表这是一块脑洞。
    1 0 1 0 0 0 1 1 1 0
    脑洞治疗仪修补某一块脑洞的基本工作原理就是将另一块连续区域挖出,将其中正常工作的脑组织填补在这块脑洞中。
    (所以脑洞治疗仪是脑洞的治疗仪?)
    例如,用上面第8号位置到第10号位置去修补第1号位置到第4号位置的脑洞。我们就会得到:
    1 1 1 1 0 0 1 0 0 0
    如果再用第1号位置到第4号位置去修补第8号位置到第10号位置:
    0 0 0 0 0 0 1 1 1 1
    这是因为脑洞治疗仪会把多余出来的脑组织直接扔掉。
    如果再用第7号位置到第10号位置去填补第1号位置到第6号位置:
    1 1 1 1 0 0 0 0 0 0
    这是因为如果新脑洞挖出来的脑组织不够多,脑洞治疗仪仅会尽量填补位置比较靠前的脑洞。
    假定初始时SHTSC并没有脑洞,给出一些挖脑洞和脑洞治疗的操作序列,你需要即时回答SHTSC的问题:
    在大脑某个区间中最大的连续脑洞区域有多大。

    Input

    第一行两个整数n,m。表示SHTSC的大脑可分为从1到n编号的n个连续区域。有m个操作。
    以下m行每行是下列三种格式之一。
    0 l r :SHTSC挖了一个从l到r的脑洞。
    1 l0 r0 l1 r2 :SHTSC进行了一次脑洞治疗,用从l0到r0的脑组织修补l1到r1的脑洞。
    2 l r :SHTSC询问l到r这段区间最大的脑洞有多大。
    n,m <=200000,1<=l<=r<=n

    Output

    对于每个询问,输出一行一个整数,表示询问区间内最大连续脑洞区域有多大。

    Sample Input

    10 10
    0 2 2
    0 4 6
    0 10 10
    2 1 10
    1 8 10 1 4
    2 1 10
    1 1 4 8 10
    2 1 10
    1 7 10 1 6
    2 1 10

    Sample Output

    3
    3
    6
    6

    HINT

     

    Source

    By 佚名上传

    线段树

    如果不用tag的话会TLE

    一开始ask写错了

    #include<iostream>
    #include<cstdio>
    #include<cmath>
    #define N 200005
    using namespace std;
    int n,m;
    struct seg
    {
        int l,r;
        int lm,rm,m,s,tag;
        int full;
    }t[N<<2];
    inline seg merge(seg a,seg b)
    {
        seg tmp;tmp.l=a.l;tmp.r=b.r;
        if(a.full)tmp.lm=a.m+b.lm;else tmp.lm=a.lm;
        if(b.full)tmp.rm=a.rm+b.m;else tmp.rm=b.rm;
        if(a.full && b.full)tmp.full=1;else tmp.full=0;
        tmp.m=max(max(a.m,b.m),a.rm+b.lm);
        tmp.s=a.s+b.s; tmp.tag=-1;
        return tmp;
    }
    void paint(int k,int v)
    {
        if(v==1)
        {
            t[k].lm=t[k].rm=t[k].m=t[k].s=0;
            t[k].full=0;
        }
        else 
        {
            t[k].lm=t[k].rm=t[k].m=t[k].s=t[k].r-t[k].l+1;
            t[k].full=1;
        }
        t[k].tag=v;
    //    if(t[k].l==t[k].r)return;
    //    paint(k<<1,v);paint(k<<1|1,v);
    }
    inline void pushup(int k)
    {t[k]=merge(t[k<<1],t[k<<1|1]);}
    inline void pushdown(int k)
    {
        if (t[k].tag!=-1)
        {
            t[k<<1].tag=t[k<<1|1].tag=t[k].tag;
            paint(k<<1,t[k].tag);paint(k<<1|1,t[k].tag);
            t[k].tag=-1;
        }
    }
    void build(int k,int l,int r)
    {
        t[k].l=l;t[k].r=r;
        t[k].lm=t[k].rm=t[k].m=t[k].s=0;
        t[k].tag=-1;t[k].full=0;
        if(l==r)return;
        int mid=(l+r)>>1;
        build(k<<1,l,mid);build(k<<1|1,mid+1,r);
        pushup(k);
    }
    int query(int k,int x,int y)
    {
        int l=t[k].l,r=t[k].r;
        if(l==x && r==y)return t[k].s;
        pushdown(k);
        int mid=(l+r)>>1;
        if(mid>=y)return query(k<<1,x,y);
        else if(mid<x)return query(k<<1|1,x,y);
        else return query(k<<1,x,mid)+query(k<<1|1,mid+1,y);
    }
    void dig(int k,int x,int y)
    {
        int l=t[k].l,r=t[k].r;
        if(l==x && r==y){paint(k,0);return;}
        pushdown(k);
        int mid=(l+r)>>1;
        if(mid>=y)dig(k<<1,x,y);
        else if(mid<x)dig(k<<1|1,x,y);
        else
        {
            dig(k<<1,x,mid);
            dig(k<<1|1,mid+1,y);
        }
        pushup(k);
    //    printf("%d %d
    ",k,x,y);
    //    printf("%d %d %d %d %d
    ",k,t[k].l,t[k].r,t[k].m,t[k].s);
    }
    void fill(int k,int x,int y,int s)
    {
        if(!s)return;
        int l=t[k].l,r=t[k].r;
        if(l==x && r==y && t[k].s<=s){paint(k,1);return;}
        pushdown(k);
        int mid=(l+r)>>1,lenl;
        if(mid>=y)fill(k<<1,x,y,s);
        else if(mid<x)fill(k<<1|1,x,y,s);
        else
        {
            lenl=query(1,x,mid);
            if(lenl<=s){fill(k<<1,x,mid,lenl);fill(k<<1|1,mid+1,y,s-lenl);}
            else fill(k<<1,x,mid,s);
        }
        pushup(k);
    }
    
    int ask(int k,int x,int y,int p)
    {
        int l=t[k].l,r=t[k].r;
        if (p==-1) if (t[k].rm>=y-x+1) return (y-x+1);else return (t[k].rm);
        else if (p==1) if (t[k].lm>=y-x+1) return y-x+1;else return t[k].lm;
        if(l==x && r==y)return t[k].m;
        if (t[k].tag!=-1)
        {
                t[k<<1].tag=t[k<<1|1].tag=t[k].tag;
                paint(k<<1,t[k].tag);paint(k<<1|1,t[k].tag);
                t[k].tag=-1;
            }     
        int mid=(l+r)>>1;
        if(mid>=y)return ask(k<<1,x,y,0);
        else if(mid<x)return ask(k<<1|1,x,y,0);
        else return max(max(ask(k<<1,x,mid,-1)+ask(k<<1|1,mid+1,y,1),ask(k<<1|1,mid+1,y,0)),ask(k<<1,x,mid,0));
    }
    /*
    void debug()
    {
        for(int k=1;k<=25;k++)
            printf("%d %d %d %d %d
    ",k,t[k].l,t[k].r,t[k].m,t[k].s);
    }
    */
    int main()
    {
        scanf("%d%d",&n,&m);
        build(1,1,n);
    //    debug();
        for(int i=0;i<m;i++)
        {
            int f;
            scanf("%d",&f);
            if(f==0)
            {
                int x,y;
                scanf("%d%d",&x,&y);
                dig(1,x,y);
    //            debug();
            }
            if(f==1)
            {
                int l0,r0,l1,r1;
                scanf("%d%d%d%d",&l0,&r0,&l1,&r1);
                int s=r0-l0+1-query(1,l0,r0);
                dig(1,l0,r0);
    //            debug();
    //            printf("%d
    ********
    ",s);
                fill(1,l1,r1,s);
    //           debug();
            }
            if(f==2)
            {
                int x,y;
                scanf("%d%d",&x,&y);
                printf("%d
    ",ask(1,x,y,0));
            }
        }
    //    system("pause");
        return 0;
    }

    感谢lxy

  • 相关阅读:
    python_ 学习笔记(hello world)
    python_ 学习笔记(运算符)
    MySQL-联合查询
    MySQL-date和datetime
    python_ 学习笔记(基本数据类型)
    python_ 学习笔记(基础语法)
    Visaul Studio 常用快捷键的动画演示
    IIS日志-网站运维的好帮手
    浅谈反射机制
    SQL Server 数据库优化文章
  • 原文地址:https://www.cnblogs.com/fdfzhyf/p/6435414.html
Copyright © 2020-2023  润新知