//Lib
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<cmath>
#include<ctime>
 
#include<iostream>
#include<algorithm>
#include<vector>
#include<string>
#include<queue>
#include<stack>
#include<set>
#include<map>
using namespace std;
//Macro
#define rep(i,a,b)  for(int i=a,tt=b;i<=tt;++i)
#define drep(i,a,b) for(int i=a,tt=b;i>=tt;--i)
#define erep(i,e,x) for(int i=x;i;i=e[i].next)
#define irep(i,x)   for(__typeof(x.begin()) i=x.begin();i!=x.end();i++)
#define read()  (strtol(ipos,&ipos,10))
#define sqr(x)  ((x)*(x))
#define pb  push_back
#define PS  system("pause");
typedef long long   ll;
typedef pair<int,int> pii;
const int oo=~0U>>1;
const double inf=1e100;
const double eps=1e-6;
string name="", in=".in", out=".out";
//Var
struct info
{
    int m,lm,rm,sum,size;
    info():size(1){}
    void set(bool x){m=lm=rm=sum=x?size:0;}
    const bool full()const{return size==sum;}
    friend info operator +(const info &a,const info &b)
    {
        info c;
        c.size=a.size+b.size;
        c.sum=a.sum+b.sum;
        c.lm=a.full()?a.sum+b.lm:a.lm;
        c.rm=b.full()?b.sum+a.rm:b.rm;
        c.m=max(max(a.m,b.m),a.rm+b.lm);
        return c;
    }
};
struct T
{
    #define lc(x)   (x<<1)
    #define rc(x)   (x<<1^1)
    info c[2];bool exist;
    T(bool f=true):exist(f){}
    void set(bool color){rep(i,0,1)c[i].set(i==color);}
    friend T operator +(const T &a,const T &b)
    {
        if(!a.exist)return b;if(!b.exist)return a;
        T c;rep(i,0,1)c.c[i]=a.c[i]+b.c[i];
        return c;
    }
}tree[262145];
int num[100008],flag[262145],n,m;
void Set(int root,int delta)
{
    if(delta==3){swap(tree[root].c[0],tree[root].c[1]);flag[root]=3-flag[root];}
    else{tree[root].set(delta-1);flag[root]=delta;}
}
void Push_Down(int root)
{
    if(flag[root])Set(lc(root),flag[root]),Set(rc(root),flag[root]),flag[root]=0;
}
void Change(int root,int l,int r,int a,int b,int delta)
{
    if(a>r||b<l)return;
    if(a<=l&&r<=b){Set(root,delta);return;}
    Push_Down(root);
    Change(lc(root),l,l+r>>1,a,b,delta);Change(rc(root),(l+r>>1)+1,r,a,b,delta);
    tree[root]=tree[lc(root)]+tree[rc(root)];
}
T Get(int root,int l,int r,int a,int b)
{
    if(a>r||b<l)return T(false);
    if(a<=l&&r<=b)return tree[root];
    Push_Down(root);
    return Get(lc(root),l,l+r>>1,a,b)+Get(rc(root),(l+r>>1)+1,r,a,b);
}
void Build(int root,int l,int r)
{
    if(l==r){tree[root].set(num[l]);return;}
    Build(lc(root),l,l+r>>1);
    Build(rc(root),(l+r>>1)+1,r);
    tree[root]=tree[lc(root)]+tree[rc(root)];
}
void Work()
{
    int o,a,b;
    scanf("%d%d",&n,&m);
    rep(i,1,n)scanf("%d",num+i);
    Build(1,1,n);
    rep(i,1,m)
    {
        scanf("%d%d%d",&o,&a,&b);a++;b++;
        switch(o)
        {
            case 0:Change(1,1,n,a,b,1);break;
            case 1:Change(1,1,n,a,b,2);break;
            case 2:Change(1,1,n,a,b,3);break;
            case 3:printf("%d\n",Get(1,1,n,a,b).c[1].sum);break;
            case 4:printf("%d\n",Get(1,1,n,a,b).c[1].m);break;
        }
    }
}
int main()
{
//  freopen((name+in).c_str(),"r",stdin);
//  freopen((name+out).c_str(),"w",stdout);
//  Init();
    Work();
    return 0;
}