• hdu 3397 Sequence operation(很有意思的线段树题)


    Sequence operation

    Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)
    Total Submission(s): 4952    Accepted Submission(s): 1452

    Problem Description
    lxhgww got a sequence contains n characters which are all '0's or '1's.
    We have five operations here:
    Change operations:
    0 a b change all characters into '0's in [a , b]
    1 a b change all characters into '1's in [a , b]
    2 a b change all '0's into '1's and change all '1's into '0's in [a, b]
    Output operations:
    3 a b output the number of '1's in [a, b]
    4 a b output the length of the longest continuous '1' string in [a , b]
     
    Input
    T(T<=10) in the first line is the case number.
    Each case has two integers in the first line: n and m (1 <= n , m <= 100000).
    The next line contains n characters, '0' or '1' separated by spaces.
    Then m lines are the operations:
    op a b: 0 <= op <= 4 , 0 <= a <= b < n.
     
    Output
    For each output operation , output the result.
     
    Sample Input
    1 10 10 0 0 0 1 1 0 1 0 1 1 1 0 2 3 0 5 2 2 2 4 0 4 0 3 6 2 3 7 4 2 8 1 0 5 0 5 6 3 3 9
     
    Sample Output
    5 2 6 5
     
    Author
    lxhgww&&shǎ崽
     
    Source
     
    Recommend
    lcy
      题意:
    给你一个0,1数组。你可以对数组进行以下操作。
    0 x y   把[x,y]之间的元素置为0。
    1 x y   把[x,y]之间的元素置为1。
    2 x y   把[x,y]之间的元素置为1变成0,0变成1。
    3 x y   求[x,y]之间元素1的个数。
    4 x y   [x,y]之间最长连续1的长度。
    思路:
    对于0,1,3,4操作都很传统。区间更新区间统计。但是由于多了2操作所以就要多维护关于0的信息。这样进行2操作的时候之间交换1和0的信息就行了。还有查询的时候也有注意的地方。开始没注意那个地方导致wa数次。反复检查冗长的代码无数次。。。。可怜我的时间呀。。。哎。。。。。
    详细见代码:
    #include<algorithm>
    #include<iostream>
    #include<string.h>
    #include<sstream>
    #include<stdio.h>
    #include<math.h>
    #include<vector>
    #include<string>
    #include<queue>
    #include<set>
    #include<map>
    using namespace std;
    const int INF=0x3f3f3f3f;
    const int maxn=100100;
    int sta[maxn<<2],ml0[maxn<<2],mr0[maxn<<2],ml1[maxn<<2];//sta为标记。ml1为1左端连续。ml0为0左端连续
    int mr1[maxn<<2],ma1[maxn<<2],ma0[maxn<<2],one[maxn<<2];//ma1为最大1连续数.one记录1的个数
    void opp(int L,int R,int k)//对于2操作。0和1互换
    {
        swap(ma0[k],ma1[k]);
        swap(ml0[k],ml1[k]);
        swap(mr0[k],mr1[k]);
        one[k]=R-L-one[k]+1;
    }
    void pushup(int L,int R,int k)//下传标记
    {
        int ls,rs,mid;
        ls=k<<1;
        rs=ls|1;
        mid=(L+R)>>1;
        ml0[k]=ml0[ls];
        mr0[k]=mr0[rs];
        ml1[k]=ml1[ls];
        mr1[k]=mr1[rs];
        if(ml0[ls]==mid-L+1)
            ml0[k]+=ml0[rs];
        if(mr0[rs]==R-mid)
            mr0[k]+=mr0[ls];
        if(ml1[ls]==mid-L+1)
            ml1[k]+=ml1[rs];
        if(mr1[rs]==R-mid)
            mr1[k]+=mr1[ls];
        ma1[k]=max(ma1[ls],ma1[rs]);
        ma1[k]=max(ma1[k],mr1[ls]+ml1[rs]);
        ma0[k]=max(ma0[ls],ma0[rs]);
        ma0[k]=max(ma0[k],mr0[ls]+ml0[rs]);
        one[k]=one[ls]+one[rs];
    }
    void pushdown(int L,int R,int k)//上传
    {
        int ls,rs,mid;
        ls=k<<1;
        rs=ls|1;
        mid=(L+R)>>1;
        //printf("mark %d->%d and %d->%d %d
    ",L,mid,mid+1,R,sta[k]);
        if(sta[k]==0)
        {
            sta[ls]=sta[rs]=0;
            ma0[ls]=ml0[ls]=mr0[ls]=mid-L+1;
            ma1[ls]=ml1[ls]=mr1[ls]=one[ls]=ma1[rs]=ml1[rs]=mr1[rs]=one[rs]=0;
            ma0[rs]=ml0[rs]=mr0[rs]=R-mid;
    
        }
        else if(sta[k]==1)
        {
            sta[ls]=sta[rs]=1;
            ma0[ls]=ml0[ls]=mr0[ls]=ma0[rs]=ml0[rs]=mr0[rs]=0;
            ma1[ls]=ml1[ls]=mr1[ls]=one[ls]=mid-L+1;
            ma1[rs]=ml1[rs]=mr1[rs]=one[rs]=R-mid;
        }
        else
        {
            if(sta[ls]!=-1)//2操作对于0,1标记直接0,1标记互换
            {
                if(sta[ls]==2)//原先有2直接变-1
                    sta[ls]=-1;
                else
                    sta[ls]^=1;
            }
            else
                sta[ls]=2;
            if(sta[rs]!=-1)
            {
                if(sta[rs]==2)
                    sta[rs]=-1;
                else
                    sta[rs]^=1;
            }
            else
                sta[rs]=2;
            opp(L,mid,ls);
            opp(mid+1,R,rs);
        }
        sta[k]=-1;
    }
    void btree(int L,int R,int k)
    {
        int ls,rs,mid;
        sta[k]=-1;
        if(L==R)
        {
            scanf("%d",&one[k]);
            if(one[k])
            {
                ma1[k]=ml1[k]=mr1[k]=1;
                ma0[k]=ml0[k]=mr0[k]=0;
            }
            else
            {
                 ma1[k]=ml1[k]=mr1[k]=0;
                 ma0[k]=ml0[k]=mr0[k]=1;
            }
            return ;
        }
        ls=k<<1;
        rs=ls|1;
        mid=(L+R)>>1;
        btree(L,mid,ls);
        btree(mid+1,R,rs);
        pushup(L,R,k);
        //printf("%d->%d
    ",L,R);
        //printf("%d---%d----%d
    ",ml1[k],mr1[k],one[k]);
    }
    void update(int L,int R,int l,int r,int k,int op)
    {
        int ls,rs,mid;
        if(l==L&&r==R)
        {
            if(op==0)
            {
                sta[k]=0;
                ma0[k]=ml0[k]=mr0[k]=R-L+1;
                ma1[k]=ml1[k]=mr1[k]=one[k]=0;
            }
            else if(op==1)
            {
                sta[k]=1;
                ma0[k]=ml0[k]=mr0[k]=0;
                ma1[k]=ml1[k]=mr1[k]=one[k]=R-L+1;
            }
            else
            {
                if(sta[k]==-1)
                    sta[k]=2;
                else if(sta[k]==2)
                    sta[k]=-1;
                else
                    sta[k]^=1;
                opp(L,R,k);
            }
            //printf("mark %d->%d %d
    ",L,R,op);
            //printf("%d->%d
    ",L,R);
            //printf("%d---%d----%d
    ",ml1[k],mr1[k],one[k]);
            return ;
        }
        if(sta[k]!=-1)
            pushdown(L,R,k);
        ls=k<<1;
        rs=ls|1;
        mid=(L+R)>>1;
        if(l>mid)
            update(mid+1,R,l,r,rs,op);
        else if(r<=mid)
            update(L,mid,l,r,ls,op);
        else
        {
            update(L,mid,l,mid,ls,op);
            update(mid+1,R,mid+1,r,rs,op);
        }
        pushup(L,R,k);
        //printf("%d->%d
    ",L,R);
        //printf("%d---%d----%d
    ",ml1[k],mr1[k],one[k]);
    }
    int qu(int L,int R,int l,int r,int k,int op)
    {
        int ls,rs,mid,tmp,ll,rr;
        if(sta[k]==0)
            return 0;
        if(sta[k]==1)
            return r-l+1;
        if(l==L&&r==R)
        {
            if(op==3)
                return one[k];
            else
                return ma1[k];
        }
        if(sta[k]!=-1)
            pushdown(L,R,k);
        ls=k<<1;
        rs=ls|1;
        mid=(L+R)>>1;
        if(l>mid)
            return qu(mid+1,R,l,r,rs,op);
        else if(r<=mid)
            return qu(L,mid,l,r,ls,op);
        else
        {
            if(op==3)
                return qu(L,mid,l,mid,ls,op)+qu(mid+1,R,mid+1,r,rs,op);
            else//4对于分离操作尤其注意!!最大值只能是以下几种情况。
            {
                tmp=max(qu(L,mid,l,mid,ls,op),qu(mid+1,R,mid+1,r,rs,op));//最大值在左儿子或右儿子中
                ll=max(mid-mr1[ls]+1,l);//最大值在中间区域
                rr=min(mid+ml1[rs],r);//注意范围
                tmp=max(tmp,rr-ll+1);
                return tmp;
            }
        }
    
    }
    int main()
    {
        int t,n,m,op,a,b;
    
        scanf("%d",&t);
        while(t--)
        {
            scanf("%d%d",&n,&m);
            btree(1,n,1);
            while(m--)
            {
                scanf("%d%d%d",&op,&a,&b);
                a++,b++;
                if(op<3)
                    update(1,n,a,b,1,op);
                else
                    printf("%d
    ",qu(1,n,a,b,1,op));
            }
        }
        return 0;
    }
    


  • 相关阅读:
    郝小亮-读王坚《在线》:互联网能做的和没做的事还有很多
    区块链的模型架构浅分析
    Springboot Application 集成 OSGI 框架开发
    java的OSGi确实是个坑
    所有围绕微信公众号,企业号开发者的企业或个人的创造的利润以及生存时间周期
    4张图让你看懂分布式架构从硬件到软件
    .NET J2EE APP全局会话架构运用场景
    ilspy导致c# dll代码被窃取
    windows+pytorch+pycharm配置
    海康-qt+opencv开发海康威视网络摄像机采集处理程序
  • 原文地址:https://www.cnblogs.com/fuhaots2009/p/3373616.html
Copyright © 2020-2023  润新知