zoukankan      html  css  js  c++  java
  • [BZOJ1858/Luogu2572][SCOI2010]序列操作

    题目链接:

    BZOJ1858

    Luogu2572

    为什么我的代码这么长啊。。

    这一看就是个线段树裸题,难点在于第(4)个操作。

    我们需要在线段树上维护(6)个值:

    Lm0/1:紧靠左的最长一段(0/1)的长度

    Rm0/1:紧靠右的最长一段(0/1)的长度

    Tm0/1:整段中的最长一段(0/1)的长度

    最后注意修改和翻转操作的优先级:修改的优先级最高(显然)。

    然后Debug就好了。

    代码:

    #include <cstdio>
    #include <algorithm>
    
    struct Segment_Tree
    {
        struct Node{int Cnt,Tag,Rev,Lm0,Lm1,Rm0,Rm1,Tm0,Tm1;}a[400005];
        //Cnt 1的个数
        //Tag -1/0/1:无修改/覆盖为0/覆盖为1
        //Rev 0/1 是否翻转
        //Lm0/Lm1/Rm0/Rm1/Tm0/Tm1 如上所述
    
        inline void Pushdown(Node &p,Node &ls,Node &rs,const int ll,const int rl)
        //将p向ls和rs传播标记
        {
            if(~p.Tag)
            //优先考虑修改
            {
                ls.Lm0=ls.Rm0=ls.Tm0=(p.Tag^1)*ll,ls.Lm1=ls.Rm1=ls.Tm1=p.Tag*ll;
                rs.Lm0=rs.Rm0=rs.Tm0=(p.Tag^1)*rl,rs.Lm1=rs.Rm1=rs.Tm1=p.Tag*rl;
                ls.Cnt=p.Tag*ll,rs.Cnt=p.Tag*rl,ls.Tag=rs.Tag=p.Tag,p.Tag=-1,p.Rev=0;
                //修改后不考虑翻转,清空标记
            }
            if(p.Rev)
            {
                if(~ls.Tag)ls.Tag^=1;if(~rs.Tag)rs.Tag^=1;
                ls.Rev^=1,rs.Rev^=1,ls.Cnt=ll-ls.Cnt,rs.Cnt=rl-rs.Cnt,p.Rev=0;
                std::swap(ls.Lm0,ls.Lm1),std::swap(rs.Lm0,rs.Lm1);
                std::swap(ls.Rm0,ls.Rm1),std::swap(rs.Rm0,rs.Rm1);
                std::swap(ls.Tm0,ls.Tm1),std::swap(rs.Tm0,rs.Tm1);
                //翻转操作,也就是0/1的信息互换
            }
        }
    
        inline Node Pushup(const Node &a,const Node &b,const int al,const int bl)
        //合并a和b,al为a的长度,bl同理
        {
            Node Res;
            Res.Cnt=a.Cnt+b.Cnt,Res.Tag=-1,Res.Rev=0;
            Res.Lm0=!a.Cnt?al+b.Lm0:a.Lm0;
            Res.Lm1=a.Cnt==al?al+b.Lm1:a.Lm1;
            Res.Rm0=!b.Cnt?bl+a.Rm0:b.Rm0;
            Res.Rm1=b.Cnt==bl?bl+a.Rm1:b.Rm1;
            Res.Tm0=std::max(std::max(a.Tm0,b.Tm0),a.Rm0+b.Lm0);
            Res.Tm1=std::max(std::max(a.Tm1,b.Tm1),a.Rm1+b.Lm1);
            return Res;
        }
    
        void Build(const int p,const int l,const int r)
        {
            if(a[p].Tag=-1,l==r)
            {
                scanf("%d",&a[p].Cnt);
                if(a[p].Cnt)a[p].Lm1=a[p].Rm1=a[p].Tm1=1;
                else a[p].Lm0=a[p].Rm0=a[p].Tm0=1;
                return;
            }
            const int Mid=(l+r)>>1;
            Build(p<<1,l,Mid),Build(p<<1|1,Mid+1,r);
            a[p]=Pushup(a[p<<1],a[p<<1|1],Mid-l+1,r-Mid);
        }
    
        void Cover(const int p,const int l,const int r,const int tl,const int tr,const int v)
        //覆盖操作
        {
            if(tl<=l&&r<=tr)
            {
                a[p].Cnt=v*(r-l+1),a[p].Tag=v;
                a[p].Lm0=a[p].Rm0=a[p].Tm0=(v^1)*(r-l+1);
                a[p].Lm1=a[p].Rm1=a[p].Tm1=v*(r-l+1);
                return;
            }
            const int Mid=(l+r)>>1;
            Pushdown(a[p],a[p<<1],a[p<<1|1],Mid-l+1,r-Mid);
            if(tl<=Mid)Cover(p<<1,l,Mid,tl,tr,v);
            if(tr>Mid)Cover(p<<1|1,Mid+1,r,tl,tr,v);
            a[p]=Pushup(a[p<<1],a[p<<1|1],Mid-l+1,r-Mid);
        }
    
        void Reverse(const int p,const int l,const int r,const int tl,const int tr)
        //翻转操作
        {
            if(tl<=l&&r<=tr)
            {
                if(~a[p].Tag)a[p].Tag^=1;
                //注意优先级
                a[p].Cnt=r-l+1-a[p].Cnt,a[p].Rev^=1;
                std::swap(a[p].Lm0,a[p].Lm1);
                std::swap(a[p].Rm0,a[p].Rm1);
                std::swap(a[p].Tm0,a[p].Tm1);
                return;
            }
            const int Mid=(l+r)>>1;
            Pushdown(a[p],a[p<<1],a[p<<1|1],Mid-l+1,r-Mid);
            if(tl<=Mid)Reverse(p<<1,l,Mid,tl,tr);
            if(tr>Mid)Reverse(p<<1|1,Mid+1,r,tl,tr);
            a[p]=Pushup(a[p<<1],a[p<<1|1],Mid-l+1,r-Mid);
        }
    
        int Query_Cnt(const int p,const int l,const int r,const int tl,const int tr)
        //查询1的个数
        {
            if(tl<=l&&r<=tr)return a[p].Cnt;
            int Mid=(l+r)>>1,Res=0;
            Pushdown(a[p],a[p<<1],a[p<<1|1],Mid-l+1,r-Mid);
            if(tl<=Mid)Res=Query_Cnt(p<<1,l,Mid,tl,tr);
            if(tr>Mid)Res+=Query_Cnt(p<<1|1,Mid+1,r,tl,tr);
            return Res;
        }
    
        Node Query_Con(const int p,const int l,const int r,const int tl,const int tr)
        //查询连续1的长度
        {
            if(tl<=l&&r<=tr)return a[p];
            const int Mid=(l+r)>>1;
            Pushdown(a[p],a[p<<1],a[p<<1|1],Mid-l+1,r-Mid);
            if(tr<=Mid)return Query_Con(p<<1,l,Mid,tl,tr);
            if(tl>Mid)return Query_Con(p<<1|1,Mid+1,r,tl,tr);
            return Pushup(Query_Con(p<<1,l,Mid,tl,tr),Query_Con(p<<1|1,Mid+1,r,tl,tr),Mid-l+1,r-Mid);
        }
    }Sequence;
    
    int main()
    {
        int n,m;scanf("%d%d",&n,&m),Sequence.Build(1,1,n);
        for(int op,l,r;m--;)
            if(scanf("%d%d%d",&op,&l,&r),++l,++r,op<=1)Sequence.Cover(1,1,n,l,r,op);
            else if(op==2)Sequence.Reverse(1,1,n,l,r);
            else if(op==3)printf("%d
    ",Sequence.Query_Cnt(1,1,n,l,r));
            else printf("%d
    ",Sequence.Query_Con(1,1,n,l,r).Tm1);
        return 0;
    }
    
  • 相关阅读:
    网络资源(4)
    网络资源(3)
    网络资源(2)
    网络资源(1)
    OCP读书笔记(27)
    OCP读书笔记(26)
    OCP读书笔记(25)
    OCP读书笔记(24)
    OCP读书笔记(23)
    OCP读书笔记(22)
  • 原文地址:https://www.cnblogs.com/LanrTabe/p/10383727.html
Copyright © 2011-2022 走看看