• bzoj1858


    题解:

    线段树

    每一次记录连续的1、0,、01个数

    然后合并

    代码:

    #include<cstdio>  
    #include<iostream>  
    #define N 400005  
    using namespace std;  
    int n,m,i,nd=0,qd,root,opt,L,R;
    int a[N],c[N][2],l[N],r[N],ml0[N];
    int ml1[N],mr0[N],mr1[N],m1[N];
    int m0[N],sum[N],tag0[N],tag1[N],rev[N];  
    void update(int x)  
    {  
        int lc=c[x][0],rc=c[x][1];  
        ml0[x]=ml0[lc];ml1[x]=ml1[lc];  
        mr0[x]=mr0[rc];mr1[x]=mr1[rc];  
        if (ml0[lc]==r[lc]-l[lc]+1)ml0[x]=ml0[lc]+ml0[rc];  
        if (ml1[lc]==r[lc]-l[lc]+1)ml1[x]=ml1[lc]+ml1[rc];  
        if (mr0[rc]==r[rc]-l[rc]+1)mr0[x]=mr0[rc]+mr0[lc];  
        if (mr1[rc]==r[rc]-l[rc]+1)mr1[x]=mr1[rc]+mr1[lc];  
        m1[x]=max(mr1[lc]+ml1[rc],max(m1[lc],m1[rc]));  
        m0[x]=max(mr0[lc]+ml0[rc],max(m0[lc],m0[rc]));  
        sum[x]=sum[lc]+sum[rc];  
    }  
    void mark0(int x)  
    {  
        tag0[x]=1;tag1[x]=0;rev[x]=0;  
        ml0[x]=mr0[x]=m0[x]=r[x]-l[x]+1;  
        ml1[x]=mr1[x]=m1[x]=sum[x]=0;  
    }  
    void mark1(int x)  
    {  
        tag1[x]=1;tag0[x]=0;rev[x]=0;  
        ml0[x]=mr0[x]=m0[x]=0;  
        ml1[x]=mr1[x]=m1[x]=sum[x]=r[x]-l[x]+1;  
    }  
    void markr(int x)  
    {  
        rev[x]^=1;  
        swap(ml0[x],ml1[x]);
        swap(mr0[x],mr1[x]);  
        swap(m0[x],m1[x]);  
        sum[x]=r[x]-l[x]+1-sum[x];  
    }  
    void down(int x)  
    {  
        if (tag0[x])mark0(c[x][0]),mark0(c[x][1]),tag0[x]=0;  
        if (tag1[x])mark1(c[x][0]),mark1(c[x][1]),tag1[x]=0;  
        if (rev[x])markr(c[x][0]),markr(c[x][1]),rev[x]=0;  
    }  
    void build(int &x,int ll,int rr)  
    {  
        x=++nd;  
        l[x]=ll;r[x]=rr;  
        tag0[x]=tag1[x]=rev[x]=0;  
        if (ll==rr)  
         {  
            c[x][0]=c[x][1]=0;  
            ml0[x]=mr0[x]=m0[x]=(a[ll]==0);  
            ml1[x]=mr1[x]=m1[x]=sum[x]=(a[ll]==1);  
            return;  
         }  
        int mid=(ll+rr)/2;  
        build(c[x][0],ll,mid);
        build(c[x][1],mid+1,rr);  
        update(x);  
    }  
    void change(int x,int ll,int rr,int k)  
    {  
        if (l[x]>rr||r[x]<ll)return;  
        down(x);  
        if (ll<=l[x]&&rr>=r[x])   
         {  
            if (k==0)mark0(x);
            else if(k==1)mark1(x);
            else markr(x);  
            return;  
         }  
        change(c[x][0],ll,rr,k);change(c[x][1],ll,rr,k);  
        update(x);  
    }  
    int query(int x,int ll,int rr)  
    {  
        if (l[x]>rr||r[x]<ll)return 0;   
        down(x);  
        if (ll<=l[x]&&rr>=r[x])return sum[x];  
        return query(c[x][0],ll,rr)+query(c[x][1],ll,rr);  
    }  
    int query1(int x,int ll,int rr)  
    {  
        down(x);  
        if (ll==l[x]&&rr==r[x])return x;  
        int mid=(l[x]+r[x])/2;  
        if (rr<=mid)return query1(c[x][0],ll,rr);  
        else if (ll>mid)return query1(c[x][1],ll,rr);else  
         {  
            int ans=++qd;  
            c[ans][0]=query1(c[x][0],ll,mid);c[ans][1]=query1(c[x][1],mid+1,rr);  
            update(ans);  
            return ans;  
         }  
    }  
    int main()  
    {  
        scanf("%d%d",&n,&m);  
        for (i=1;i<=n;i++)scanf("%d",&a[i]);  
        build(root,1,n);  
        for (i=1;i<=m;i++)  
         {  
            scanf("%d%d%d",&opt,&L,&R);  
            if (opt==0||opt==1||opt==2) change(root,L+1,R+1,opt);  
            else  
             {  
                if (opt==3) printf("%d
    ",query(root,L+1,R+1)); 
                else qd=nd,printf("%d
    ",m1[query1(root,L+1,R+1)]);  
             }  
         }  
    } 
  • 相关阅读:
    SX知识学习——sources
    SX知识学习——TCGA(转)
    SX知识学习——WES(转)
    SX知识学习——CHIPseq(转+总结)
    编译软件安装——VS2010
    数据库知识学习——mysql
    计算机知识学习——操作系统
    计算机知识学习——计算机组成原理
    Scrapy 中文手册 0.25 文档
    python Requests 库
  • 原文地址:https://www.cnblogs.com/xuanyiming/p/8481938.html
Copyright © 2020-2023  润新知