bzoj1858序列操作 线段树

来源:互联网 发布:重装ubuntu系统分区 编辑:程序博客网 时间:2024/05/17 01:56

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

#include<iostream>#include<cstdio>#include<cstring>#define N 100005using 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;}
0 0