Link_Cut_Y @ 2021-09-04 14:14:46
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;
const int N=100010;
struct SegmentTree
{
int l,r;
int sum;
int lazy;
int rev;
int max[2];
int l_max[2];
int r_max[2];
}tr[N<<2];
int n,m;
int a[N];
void pushup(int u)
{
tr[u].sum=tr[u<<1].sum+tr[u<<1|1].sum;
for(int i=0;i<=1;i++)
{
tr[u].l_max[i]=tr[u<<1].l_max[i];
if(i==1 && tr[u<<1].sum==tr[u<<1].r-tr[u<<1].l+1) tr[u].l_max[i]+=tr[u<<1|1].l_max[i];
else if(i==0 && tr[u<<1].sum==0) tr[u].l_max[i]+=tr[u<<1|1].l_max[i];
tr[u].r_max[i]=tr[u<<1].r_max[i];
if(i==1 && tr[u<<1|1].sum==tr[u<<1|1].r-tr[u<<1|1].l+1) tr[u].r_max[i]+=tr[u<<1|1].r_max[i];
else if(i==0 && tr[u<<1|1].sum==0) tr[u].r_max[i]+=tr[u<<1|1].r_max[i];
auto &root=tr[u];
auto &l=tr[u<<1];
auto &r=tr[u<<1|1];
root.max[i]=l.r_max[i]+r.l_max[i];
root.max[i]=max(root.max[i],l.max[i]);
root.max[i]=max(root.max[i],r.max[i]);
}
}
void build(int u,int l,int r)
{
auto &root=tr[u];
tr[u]={l,r};
tr[u].lazy=-1;
if(l==r)
{
root.sum=a[l];
root.max[0]=root.l_max[0]=root.r_max[0]=a[l]==0;
root.max[1]=root.l_max[1]=root.r_max[1]=a[l]==1;
return;
}
int mid=(l+r)>>1;
build(u<<1,l,mid);
build(u<<1|1,mid+1,r);
pushup(u);
}
void pushdown(int u)
{
auto &root=tr[u];
auto &l=tr[u<<1];
auto &r=tr[u<<1|1];
if(root.lazy!=-1)
{
root.rev=0;
int val=root.lazy;
l.sum=(l.r-l.l+1)*val;
r.sum=(r.r-r.l+1)*val;
l.lazy=r.lazy=val;
l.rev=r.rev=0;
l.max[val]
=l.l_max[val]
=l.r_max[val]
=l.r-l.l+1;
l.max[val^1]
=l.l_max[val^1]
=r.r_max[val^1]
=0;
r.max[val]
=r.l_max[val]
=r.r_max[val]
=r.r-r.l+1;
r.max[val^1]
=r.l_max[val^1]
=r.r_max[val^1]
=0;
root.lazy=-1;
}
if(root.rev)
{
l.sum=(l.r-l.l+1)-l.sum;
r.sum=(r.r-r.l+1)-r.sum;
if(l.lazy!=-1) l.lazy^=1;
else l.rev^=1;
if(r.lazy!=-1) r.lazy^=1;
else r.rev^=1;
swap(l.max[0],l.max[1]);
swap(l.l_max[0],l.l_max[1]);
swap(l.r_max[0],l.r_max[1]);
swap(r.max[0],r.max[1]);
swap(r.l_max[0],r.l_max[1]);
swap(r.r_max[0],r.r_max[1]);
root.rev=0;
}
}
void modify(int u,int val,int l,int r)
{
pushdown(u);
auto &root=tr[u];
if(root.l==l && root.r==r)
{
if(val==0 || val==1)
{
root.sum=(root.r-root.l+1)*val;
root.lazy=val;
root.max[val]
=root.l_max[val]
=root.r_max[val]
=root.r-root.l+1;
root.max[val^1]
=root.l_max[val^1]
=root.r_max[val^1]
=0;
}
else if(val==2)
{
root.sum=(root.r-root.l+1)-root.sum;
root.rev^=1;
swap(root.max[1],root.max[0]);
swap(root.l_max[1],root.l_max[0]);
swap(root.r_max[1],root.r_max[0]);
}
return;
}
int mid=(root.l+root.r)>>1;
if(l>mid) modify(u<<1|1,val,l,r);
else if(r<=mid) modify(u<<1,val,l,r);
else modify(u<<1,val,l,mid),modify(u<<1|1,val,mid+1,r);
pushup(u);
}
int query(int u,int l,int r)
{
auto &root=tr[u];
pushdown(u);
if(root.l==l && root.r==r) return root.sum;
int mid=(root.l+root.r)>>1;
if(mid<l) return query(u<<1|1,l,r);
else if(r<=mid) return query(u<<1,l,r);
else return query(u<<1,l,mid)+query(u<<1|1,mid+1,r);
}
SegmentTree query_max(int u,int l,int r)
{
auto &root=tr[u];
pushdown(u);
if(root.l==l && root.r==r) return root;
int mid=(root.l+root.r)>>1;
if(mid<l) return query_max(u<<1|1,l,r);
else if(mid>=r) return query_max(u<<1,l,r);
else
{
SegmentTree ret;
SegmentTree ll=query_max(u<<1,l,mid),rr=query_max(u<<1|1,mid+1,r);
ret.sum=ll.sum+rr.sum;
for(int i=0;i<=1;i++)
{
ret.l_max[i]=ll.l_max[i];
if(i==1 && ll.sum==ll.r-ll.l+1) ret.l_max[i]+=rr.l_max[i];
else if(i==0 && ll.sum==0) ret.l_max[i]+=rr.l_max[i];;
ret.r_max[i]=rr.r_max[i];
if(i==1 && rr.sum==rr.r-rr.l+1) ret.r_max[i]+=ll.r_max[i];
else if(i==0 && rr.sum==0) ret.r_max[i]+=ll.r_max[i];
ret.max[i]=ll.r_max[i]+rr.l_max[i];
ret.max[i]=max(ret.max[i],ll.max[i]);
ret.max[i]=max(ret.max[i],rr.max[i]);
}
return ret;
}
}
int main()
{
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++) scanf("%d",&a[i]);
build(1,1,n);
int opt,l,r;
while(m--)
{
scanf("%d%d%d",&opt,&l,&r);
l++,r++;
if(opt==0) modify(1,0,l,r);
else if(opt==1) modify(1,1,l,r);
else if(opt==2) modify(1,2,l,r);
else if(opt==3) printf("%d\n",query(1,l,r));
else printf("%d\n",query_max(1,l,r).max[1]);
}
return 0;
}