• BZOJ1858:[SCOI2010]序列操作——题解


    https://www.lydsy.com/JudgeOnline/problem.php?id=1858

    lxhgww最近收到了一个01序列,序列里面包含了n个数,这些数要么是0,要么是1,现在对于这个序列有五种变换操作和询问操作:

    0 a b 把[a, b]区间内的所有数全变成0

    1 a b 把[a, b]区间内的所有数全变成1

    2 a b 把[a,b]区间内的所有数全部取反,也就是说把所有的0变成1,把所有的1变成0

    3 a b 询问[a, b]区间内总共有多少个1

    4 a b 询问[a, b]区间内最多有多少个连续的1

    对于每一种询问操作,lxhgww都需要给出回答,聪明的程序员们,你们能帮助他吗?

    线段树嘛,很裸的,正好趁自己神志不清试着来写写吧。

    woc这线段树真恶心,2个标记维护7个量!

    显然需要维护区间1个数,区间最大连续1。

    为了合并还需要维护区间左最大连续1和右最大连续1.

    为了取反还需要把上述东西的0也给求出来。

    之后你愉快的敲起了数组线段树,结果发现你4操作写起来贼费劲。

    靠!改结构体!

    然后就是两个标记纠缠不清的问题了。

    于是过了三次拍,debug了三次,终于过了……

    2h+考场直接gg。

    #include<map>
    #include<cmath>
    #include<stack>
    #include<queue>
    #include<cstdio>
    #include<cctype>
    #include<vector>
    #include<cstdlib>
    #include<cstring>
    #include<iostream>
    #include<algorithm>
    using namespace std;
    const int N=1e5+5;
    const int p=1e9+7;
    inline int read(){
        int X=0,w=0;char ch=0;
        while(!isdigit(ch)){w|=ch=='-';ch=getchar();}
        while(isdigit(ch))X=(X<<3)+(X<<1)+(ch^48),ch=getchar();
        return w?-X:X;
    }
    struct node{
        int l,r,ls0,rs0,ls1,rs1;
        int lz,sum,rng0,rng1;
        bool rev;
    }t[N*4];
    int n,m,b[N];
    inline void upt(int a,int l,int r){
        int mid=(l+r)>>1,ls=a<<1,rs=a<<1|1;
        t[a].sum=t[ls].sum+t[rs].sum;
        t[a].rng1=max(t[ls].rs1+t[rs].ls1,max(t[ls].rng1,t[rs].rng1));
        t[a].rng0=max(t[ls].rs0+t[rs].ls0,max(t[ls].rng0,t[rs].rng0));
        t[a].ls1=t[ls].ls1+(t[ls].ls1==mid-l+1?t[rs].ls1:0);
        t[a].rs1=t[rs].rs1+(t[rs].rs1==r-mid?t[ls].rs1:0);
        t[a].ls0=t[ls].ls0+(t[ls].ls0==mid-l+1?t[rs].ls0:0);
        t[a].rs0=t[rs].rs0+(t[rs].rs0==r-mid?t[ls].rs0:0);
    }
    inline void turn(int a){
        t[a].sum=t[a].r-t[a].l+1-t[a].sum;
        swap(t[a].ls1,t[a].ls0);
        swap(t[a].rs1,t[a].rs0);
        swap(t[a].rng1,t[a].rng0);
    }
    inline void change(int a,int w){
        if(w){
        t[a].ls1=t[a].rs1=t[a].sum=t[a].rng1=t[a].r-t[a].l+1;
        t[a].ls0=t[a].rs0=t[a].rng0=0;
        }
        else{
        t[a].ls0=t[a].rs0=t[a].rng0=t[a].r-t[a].l+1;
        t[a].ls1=t[a].rs1=t[a].sum=t[a].rng1=0;
        }
        t[a].rev=0;
    }
    inline void push(int a){
        int ls=a<<1,rs=a<<1|1;
        if(t[a].lz!=-1){
        change(ls,t[a].lz);change(rs,t[a].lz);
        t[ls].lz=t[rs].lz=t[a].lz;t[a].lz=-1;
        }
        if(t[a].rev){
        turn(ls);turn(rs);
        t[ls].rev^=1;t[rs].rev^=1;t[a].rev=0;
        }
    }
    void build(int a,int l,int r){
        t[a].lz=-1;t[a].rev=0;t[a].l=l;t[a].r=r;
        if(l==r){
        t[a].sum=b[l];
        if(b[l])t[a].ls1=t[a].rs1=t[a].rng1=1;
        else t[a].ls0=t[a].rs0=t[a].rng0=1;
        return;
        }
        int mid=(l+r)>>1;
        build(a<<1,l,mid);build(a<<1|1,mid+1,r);
        upt(a,l,r);
    }
    void modify(int a,int l,int r,int l1,int r1,int w){
        if(r<l1||r1<l)return;
        if(l1<=l&&r<=r1){
        t[a].lz=w;change(a,w);
        return;
        }
        push(a);
        int mid=(l+r)>>1;
        modify(a<<1,l,mid,l1,r1,w);
        modify(a<<1|1,mid+1,r,l1,r1,w);
        upt(a,l,r);
    }
    void reverse(int a,int l,int r,int l1,int r1){
        if(r<l1||r1<l)return;
        if(l1<=l&&r<=r1){
        t[a].rev^=1;turn(a);
        return;
        }
        push(a);
        int mid=(l+r)>>1;
        reverse(a<<1,l,mid,l1,r1);
        reverse(a<<1|1,mid+1,r,l1,r1);
        upt(a,l,r);    
    }
    int query_sum(int a,int l,int r,int l1,int r1){
        if(r<l1||r1<l)return 0;
        if(l1<=l&&r<=r1)return t[a].sum;
        push(a);
        int mid=(l+r)>>1;
        return query_sum(a<<1,l,mid,l1,r1)+
        query_sum(a<<1|1,mid+1,r,l1,r1);
    }
    node query_rng(int a,int l,int r,int l1,int r1){
        if(l1==l&&r==r1)return t[a];
        push(a);
        int mid=(l+r)>>1;
        if(mid>=r1)return query_rng(a<<1,l,mid,l1,r1);
        else if(mid+1<=l1)return query_rng(a<<1|1,mid+1,r,l1,r1);
        node lans=query_rng(a<<1,l,mid,l1,mid);
        node rans=query_rng(a<<1|1,mid+1,r,mid+1,r1);
        node ans;
        ans.l=lans.l;ans.r=rans.r;
        ans.rng1=max(lans.rs1+rans.ls1,max(lans.rng1,rans.rng1));
        ans.rng0=max(lans.rs0+rans.ls0,max(lans.rng0,rans.rng0));
        ans.ls1=lans.ls1+(lans.ls1==mid-l+1?rans.ls1:0);
        ans.rs1=rans.rs1+(rans.rs1==r-mid?lans.rs1:0);
        ans.ls0=lans.ls0+(lans.ls0==mid-l+1?rans.ls0:0);
        ans.rs0=rans.rs0+(rans.rs0==r-mid?lans.rs0:0);
        return ans;
    }
    int main(){
        n=read(),m=read();
        for(int i=1;i<=n;i++)b[i]=read();
        build(1,1,n);
        while(m--){
        int op=read(),l=read()+1,r=read()+1;
        if(op==0)modify(1,1,n,l,r,0);
        if(op==1)modify(1,1,n,l,r,1);
        if(op==2)reverse(1,1,n,l,r);
        if(op==3)printf("%d
    ",query_sum(1,1,n,l,r));
        if(op==4)printf("%d
    ",query_rng(1,1,n,l,r).rng1);
        }
        return 0;
    }

    +++++++++++++++++++++++++++++++++++++++++++

    +本文作者:luyouqi233。               +

    +欢迎访问我的博客:http://www.cnblogs.com/luyouqi233/+

    +++++++++++++++++++++++++++++++++++++++++++

  • 相关阅读:
    【JAVASCRIPT】call和apply的用法以及区别
    web开发中的支付宝支付和微信支付
    【input】标签去除默认样式
    npm run build后如何打开index.html跑起项目
    Sass的混合-@mixin,@include
    ios h5 长按时出现黑色透明遮罩
    ios h5 长按放大镜效果关闭
    vue.$nextTick 解决了哪些问题
    原生JS代码封装(将字符串转换为日期 2019.08.24 )
    原生JS代码封装(获取年月日时分秒 )
  • 原文地址:https://www.cnblogs.com/luyouqi233/p/9187366.html
Copyright © 2020-2023  润新知