题目大意: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;
}