zoukankan      html  css  js  c++  java
  • BZOJ 1858【线段树】

     题意:
     0 a b 把 [a, b] 区间内的所有数全变成0
     1 a b 把 [a, b] 区间内的所有数全变成1
     2 a b 把 [a,b] 区间内的所有数全部取反
     3 a b 询问 [a, b] 区间内总共有多少个1
     4 a b 询问 [a, b] 区间内最多有多少个连续的1
     思路:
    首先 线段树 可以搞个标记 flag 是否都是 1(flag=1)/0(flag=-1) LAZY一下
    询问区间有多少个 1 ,那就是求和而已?
    询问区间最多有多少个连续的1 ?
    主要是区间合并的时候要判断
    左儿子的Right_Num ==1 && 右儿子的Left_Num ==1 然后还要算下这段区间,和最大值比较。

    so,我再搞两个值,一个结点区间的 左端点 连续为 1 的距离,右端点 连续为1 的距离
    后面发现还要再添,一个结点区间的 左端点 连续为 0 的距离,右端点 连续为0 的距离,方便反转


    现在发现,线段树 就是个 大模拟= =、好像所有的东西都是大模拟。。

    #include<bits/stdc++.h>
    using namespace std;
    typedef long long LL;
    
    const int N=1e5+10;
    
    struct Seg{
        int Left,Right;
        int Flag;       //标记
        int Sum;       //区间1的个数
        int Max_Len;    //区间 连续 1的 最长长度
        int Left_Len1,Right_Len1;  //区间左端点连续为1的距离,右端点 连续为1 的距离
        int Left_Len0,Right_Len0;   //区间左端点连续为0的距离,右端点 连续为0 的距离
    }q[N*4];
    
    void Pushdown(int num)
    {
        if(!q[num].Flag) return;
        if(q[num].Flag==1)
        {
            q[num<<1].Sum=q[num<<1].Left_Len1=q[num<<1].Right_Len1=q[num<<1].Max_Len=(q[num<<1].Right-q[num<<1].Left+1);
            q[num<<1].Left_Len0=q[num<<1].Right_Len0=0;
            q[num<<1].Flag=1;
    
            q[num<<1|1].Sum=q[num<<1|1].Left_Len1=q[num<<1|1].Right_Len1=q[num<<1|1].Max_Len=(q[num<<1|1].Right-q[num<<1|1].Left+1);
            q[num<<1|1].Left_Len0=q[num<<1|1].Right_Len0=0;
            q[num<<1|1].Flag=1;
    
            q[num].Flag=0;
        }
        else
        {
            q[num<<1].Sum=q[num<<1].Left_Len1=q[num<<1].Right_Len1=q[num<<1].Max_Len=0;
            q[num<<1].Left_Len0=q[num<<1].Right_Len0=(q[num<<1].Right-q[num<<1].Left+1);
            q[num<<1].Flag=-1;
    
            q[num<<1|1].Sum=q[num<<1|1].Left_Len1=q[num<<1|1].Right_Len1=q[num<<1|1].Max_Len=0;
            q[num<<1|1].Left_Len0=q[num<<1|1].Right_Len0=(q[num<<1|1].Right-q[num<<1|1].Left+1);
            q[num<<1|1].Flag=-1;
    
            q[num].Flag=0;
        }
    }
    
    void Pushup(int num)
    {
        if(q[num].Sum==(q[num].Right-q[num].Left+1))
        {
            q[num].Flag=1;
            q[num].Left_Len1=q[num].Right_Len1=q[num].Max_Len=q[num].Sum;
            q[num].Left_Len0=q[num].Right_Len0=0;
        }
        else if(!q[num].Sum)
        {
            q[num].Flag=-1;
            q[num].Left_Len1=q[num].Right_Len1=q[num].Max_Len=q[num].Sum;
            q[num].Left_Len0=q[num].Right_Len0=q[num].Right-q[num].Left+1;
        }
        else
        {
            q[num].Flag=0;
    
            int Max=max(q[num<<1].Max_Len,q[num<<1|1].Max_Len);
            Max=max(q[num<<1].Right_Len1+q[num<<1|1].Left_Len1,Max);
            q[num].Max_Len=Max;
    
            if(q[num<<1].Left_Len1==(q[num<<1].Right-q[num<<1].Left+1))
            {
                q[num].Left_Len1=q[num<<1].Left_Len1+q[num<<1|1].Left_Len1;
                q[num].Left_Len0=0;
            }
            else
            {
                q[num].Left_Len1=q[num<<1].Left_Len1;
    
                if(q[num<<1].Left_Len0==(q[num<<1].Right-q[num<<1].Left+1))
                    q[num].Left_Len0=q[num<<1].Left_Len0+q[num<<1|1].Left_Len0;
                else
                    q[num].Left_Len0=q[num<<1].Left_Len0;
            }
    
            if(q[num<<1|1].Right_Len1==(q[num<<1|1].Right-q[num<<1|1].Left+1))
            {
                q[num].Right_Len1=q[num<<1].Right_Len1+q[num<<1|1].Right_Len1;
                q[num].Right_Len0=0;
            }
            else
            {
                q[num].Right_Len1=q[num<<1|1].Right_Len1;
                if(q[num<<1|1].Right_Len0==(q[num<<1|1].Right-q[num<<1|1].Left+1))
                    q[num].Right_Len0=q[num<<1].Right_Len0+q[num<<1|1].Right_Len0;
                else
                    q[num].Right_Len0=q[num<<1|1].Right_Len0;
            }
        }
    }
    
    void Build(int num,int Left,int Right)
    {
        q[num].Left=Left;q[num].Right=Right;
        if(Left==Right)
        {
            scanf("%d",&q[num].Sum);
            if(q[num].Sum==1) q[num].Flag=1;
            else q[num].Flag=-1;
            q[num].Left_Len1=q[num].Right_Len1=q[num].Max_Len=q[num].Sum;
            q[num].Left_Len0=q[num].Right_Len0=1-q[num].Sum;
            return;
        }
        int Mid=(q[num].Left+q[num].Right)>>1;
        Build(num<<1,Left,Mid);
        Build(num<<1|1,Mid+1,Right);
    
        q[num].Sum=q[num<<1].Sum+q[num<<1|1].Sum;
        Pushup(num);
    }
    
    void Update1(int num,int Left,int Right)
    {
        if(q[num].Left>=Left && q[num].Right<=Right)
        {
            q[num].Flag=-1;
            q[num].Left_Len1=q[num].Right_Len1=q[num].Max_Len=q[num].Sum=0;
            q[num].Left_Len0=q[num].Right_Len0=q[num].Right-q[num].Left+1;
            return;
        }
        Pushdown(num);
    
        int Mid=(q[num].Left+q[num].Right)>>1;
        if(Mid>=Right) Update1(num<<1,Left,Right);
        else if(Mid<Left) Update1(num<<1|1,Left,Right);
        else
        {
            Update1(num<<1,Left,Mid);
            Update1(num<<1|1,Mid+1,Right);
        }
    
        q[num].Sum=q[num<<1].Sum+q[num<<1|1].Sum;
        Pushup(num);
    }
    
    void Update2(int num,int Left,int Right)
    {
        if(q[num].Left>=Left && q[num].Right<=Right)
        {
            q[num].Flag=1;
            q[num].Left_Len1=q[num].Right_Len1=q[num].Max_Len=q[num].Sum=(q[num].Right-q[num].Left+1);
            q[num].Left_Len0=q[num].Right_Len0=0;
            return;
        }
    
        Pushdown(num);
    
        int Mid=(q[num].Left+q[num].Right)>>1;
        if(Mid>=Right) Update2(num<<1,Left,Right);
        else if(Mid<Left) Update2(num<<1|1,Left,Right);
        else
        {
            Update2(num<<1,Left,Mid);
            Update2(num<<1|1,Mid+1,Right);
        }
    
        q[num].Sum=q[num<<1].Sum+q[num<<1|1].Sum;
        Pushup(num);
    }
    
    void Update3(int num,int Left,int Right)
    {
        if(q[num].Left>=Left && q[num].Right<=Right && (q[num].Sum==0||q[num].Sum==(q[num].Right-q[num].Left+1)))
        {
            if(q[num].Sum==(q[num].Right-q[num].Left+1)) q[num].Flag=-1;
            else q[num].Flag=1;
            q[num].Max_Len=q[num].Sum=q[num].Right-q[num].Left+1-q[num].Sum;
            swap(q[num].Right_Len0,q[num].Right_Len1);
            swap(q[num].Left_Len0,q[num].Left_Len1);
            return;
        }
    
        Pushdown(num);
    
        int Mid=(q[num].Left+q[num].Right)>>1;
        if(Mid>=Right) Update3(num<<1,Left,Right);
        else if(Mid<Left) Update3(num<<1|1,Left,Right);
        else
        {
            Update3(num<<1,Left,Mid);
            Update3(num<<1|1,Mid+1,Right);
        }
    
        q[num].Sum=q[num<<1].Sum+q[num<<1|1].Sum;
        Pushup(num);
    }
    
    int Query(int num,int Left,int Right)
    {
        if(q[num].Left>=Left && q[num].Right<=Right)
            return q[num].Sum;
        Pushdown(num);
        int Mid=(q[num].Left+q[num].Right)>>1;
        if(Mid>=Right)
            return Query(num<<1,Left,Right);
        else if(Mid<Left)
            return Query(num<<1|1,Left,Right);
        else
            return Query(num<<1,Left,Mid)+Query(num<<1|1,Mid+1,Right);
    }
    
    int MaxLen(int num,int Left,int Right)
    {
        if(q[num].Left>=Left && q[num].Right<=Right) return q[num].Max_Len;
        Pushdown(num);
        int Mid=(q[num].Left+q[num].Right)>>1;
        if(Mid>=Right) return MaxLen(num<<1,Left,Right);
        else if(Mid<Left) return MaxLen(num<<1|1,Left,Right);
        else
        {
            int Len1=MaxLen(num<<1,Left,Mid);
            int Len2=MaxLen(num<<1|1,Mid+1,Right);
            int Len3=min(q[num<<1].Right_Len1,Mid-Left+1) + min(q[num<<1|1].Left_Len1,Right-Mid);
            return max(Len1,max(Len2,Len3));
        }
    }
    
    int main()
    {
        int n,m,x;
        int Left,Right;
        scanf("%d%d",&n,&m);
        Build(1,1,n);
    
        while(m--){
            scanf("%d%d%d",&x,&Left,&Right);
            Left++;Right++;
            switch(x)
            {
                case 0: { Update1(1,Left,Right); break;}
                case 1: { Update2(1,Left,Right); break;}
                case 2: { Update3(1,Left,Right); break;}
                case 3: { printf("%d
    ",Query(1,Left,Right)); break;}
                case 4: { printf("%d
    ",MaxLen(1,Left,Right)); break;}
            }
        }
        return 0;
    }
    






  • 相关阅读:
    caffe源码整个训练过程
    设计模式--工厂模式 caffe_layer注册
    【Oracle】跟踪文件目录(User_Dump_Dest)生成脚本(11g/9i).txt
    【Oracle】修改参数的同时添加注释
    【Oracle】重置参数
    【Oracle】SCOPE=MEMORY|SPFILE|BOTH
    【Oracle】解锁用户
    【Oracle】开、关、删归档日志(archivelog)
    【Oracle】Rman简介
    【Oracle】非RMAN恢复数据文件、控制文件
  • 原文地址:https://www.cnblogs.com/keyboarder-zsq/p/6777339.html
Copyright © 2011-2022 走看看