bzoj1858序列操作 线段树

题目大意:01序列 可覆盖取反查询区间最长连续1 区间1的个数
BZOJ1858序列操作
记录多个信息 maxlen需要技巧 #滑稽

#include<iostream>
#include<cstdio>
#include<cstring>
#define N 100005
using namespace std;
struct Seg {int l,r,mx[2],ln[2],rn[2],sum[2],cov,rev;}t[N*4];
int a[N],n,m;
Seg merge(Seg a,Seg b){
    if(a.rev==-1) return b;
    if(b.rev==-1) return a;
    Seg tmp;
    tmp.l=a.l;tmp.r=b.r;
    tmp.cov=-1;tmp.rev=0;
    for(int i=0;i<=1;i++){
        tmp.ln[i]=a.ln[i]==(a.r-a.l+1)?a.ln[i]+b.ln[i]:a.ln[i];
        tmp.rn[i]=b.rn[i]==(b.r-b.l+1)?b.rn[i]+a.rn[i]:b.rn[i];
        tmp.mx[i]=max(a.mx[i],b.mx[i]);
        if(a.rn[i] && b.ln[i])
            tmp.mx[i]=max(a.rn[i]+b.ln[i],tmp.mx[i]);
        tmp.sum[i]=a.sum[i]+b.sum[i];
    }
    return tmp;
}
void newcover(int k){
    int r=t[k].r,l=t[k].l;
    t[k].ln[0]=t[k].rn[0]=t[k].sum[0]=t[k].mx[0]=t[k].cov==0?(r-l+1):0;
    t[k].ln[1]=t[k].rn[1]=t[k].sum[1]=t[k].mx[1]=t[k].cov==1?(r-l+1):0;
}
void newrev(int k){
    swap(t[k].ln[0],t[k].ln[1]);
    swap(t[k].rn[0],t[k].rn[1]);
    swap(t[k].sum[0],t[k].sum[1]);
    swap(t[k].mx[0],t[k].mx[1]);
}
void pushup(int k){
    t[k]=merge(t[k<<1],t[k<<1|1]);
}
void pushdown(int k){
    if(t[k].cov!=-1) {
        t[k<<1].cov=t[k<<1|1].cov=t[k].cov;t[k].cov=-1;
        t[k<<1].rev=0;t[k<<1|1].rev=0;
        newcover(k<<1);newcover(k<<1|1);return;
    }
    if(t[k].rev==1){
        if(t[k<<1].cov!=-1) t[k<<1].cov^=1;
        else t[k<<1].rev^=t[k].rev;
        if(t[k<<1|1].cov!=-1) t[k<<1|1].cov^=1;
        else t[k<<1|1].rev^=t[k].rev;
        t[k].rev=0;
        newrev(k<<1);newrev(k<<1|1);return;
    }
}
void build(int k,int l,int r){
    if(l==r){
        t[k].l=t[k].r=l;t[k].cov=a[l];t[k].rev=0;
        newcover(k);return;
    }
    int mid=(l+r)>>1;
    build(k<<1,l,mid);build(k<<1|1,mid+1,r);
    pushup(k);
}
void cover(int k,int a,int b,int x){
    int l=t[k].l,r=t[k].r;
    if(b<l || r<a) return;
    if(a<=l && r<=b){
        t[k].rev=0;t[k].cov=x;
        newcover(k);return;
    }
    pushdown(k);
    cover(k<<1,a,b,x);cover(k<<1|1,a,b,x);
    pushup(k);
}
void rev(int k,int a,int b){
    int l=t[k].l,r=t[k].r;
    if(b<l || r<a) return;
    if(a<=l && r<=b){
        if(t[k].cov!=-1) t[k].cov^=1,newcover(k);
        else t[k].rev^=1,newrev(k);return;
    }
    pushdown(k);
    rev(k<<1,a,b);rev(k<<1|1,a,b);
    pushup(k);
}
int asksum(int k,int a,int b){
    int l=t[k].l,r=t[k].r;
    if(b<l || r<a) return 0;
    if(a<=l && r<=b) return t[k].sum[1];
    pushdown(k);
    return asksum(k<<1,a,b)+asksum(k<<1|1,a,b);
}
Seg asklen(int k,int a,int b){
    int l=t[k].l,r=t[k].r;
    if(b<l || r<a) return t[0];
    if(a<=l && r<=b) return t[k];
    pushdown(k);
    return merge(asklen(k<<1,a,b),asklen(k<<1|1,a,b));
}
int main(){
    freopen("in.txt","r",stdin);
    freopen("out.txt","w",stdout);
    scanf("%d%d",&n,&m);
    for(int i=1;i<=n;i++) scanf("%d",&a[i]);
    build(1,1,n);t[0].rev=-1;
    for(int i=1;i<=m;i++){
        int opt,a,b;
        scanf("%d%d%d",&opt,&a,&b);a++;b++;
        if(opt==0) cover(1,a,b,0);
        if(opt==1) cover(1,a,b,1);
        if(opt==2) rev(1,a,b);
        if(opt==3) printf("%d\n",asksum(1,a,b));
        if(opt==4) printf("%d\n",asklen(1,a,b).mx[1]);
    }
    return 0;
}

你可能感兴趣的:(线段树,bzoj)