#include<bits/stdc++.h>
#define pb push_back
#define is insert
#define fi first
#define se second
#define INF INT_MAX
#define int long long
#define Mod(a,m) (((a)%(m)+(m))%(m))
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef pair<int,int> pii;
const int N=1e5+5;
int n,q,a[N];
struct Node{int l,r,cnt[3],lzy[3];ll nxd,val[3][3];}tr[N<<2];
void pushup(int u){
for(int i=0;i<3;i++) tr[u].cnt[i]=tr[u<<1].cnt[i]+tr[u<<1|1].cnt[i];
for(int i=0;i<3;i++){
for(int j=0;j<3;j++){
if(i==j) continue;
tr[u].val[i][j]=tr[u<<1].val[i][j]+tr[u<<1|1].val[i][j]+1ll*tr[u<<1].cnt[i]*tr[u<<1|1].cnt[j];
}
}
tr[u].nxd=tr[u].val[1][0]+tr[u].val[2][0]+tr[u].val[2][1];
}
void pushdown(int u){
if(tr[u].lzy[0]==0&&tr[u].lzy[1]==1&&tr[u].lzy[2]==2) return;
memcpy(tr[u<<1].lzy,tr[u].lzy,sizeof tr[u].lzy);
memcpy(tr[u<<1|1].lzy,tr[u].lzy,sizeof tr[u].lzy);
int cnt[3];ll val[3][3];
memcpy(cnt,tr[u<<1].cnt,sizeof tr[u<<1].cnt);
memset(tr[u<<1].cnt,0,sizeof tr[u<<1].cnt);
for(int i=0;i<3;i++) tr[u<<1].cnt[tr[u<<1].lzy[i]]+=cnt[i];
memcpy(val,tr[u<<1].val,sizeof tr[u<<1].val);
memset(tr[u<<1].val,0,sizeof tr[u<<1].val);
for(int i=0;i<3;i++) for(int j=0;j<3;j++) if(i!=j) tr[u<<1].val[tr[u<<1].lzy[i]][tr[u<<1].lzy[j]]+=val[i][j];
tr[u<<1].nxd=tr[u<<1].val[1][0]+tr[u<<1].val[2][0]+tr[u<<1].val[2][1];
memcpy(cnt,tr[u<<1|1].cnt,sizeof tr[u<<1|1].cnt);
memset(tr[u<<1|1].cnt,0,sizeof tr[u<<1|1].cnt);
for(int i=0;i<3;i++) tr[u<<1|1].cnt[tr[u<<1|1].lzy[i]]+=cnt[i];
memcpy(val,tr[u<<1|1].val,sizeof tr[u<<1|1].val);
memset(tr[u<<1|1].val,0,sizeof tr[u<<1|1].val);
for(int i=0;i<3;i++) for(int j=0;j<3;j++) if(i!=j) tr[u<<1|1].val[tr[u<<1|1].lzy[i]][tr[u<<1|1].lzy[j]]+=val[i][j];
tr[u<<1|1].nxd=tr[u<<1|1].val[1][0]+tr[u<<1|1].val[2][0]+tr[u<<1|1].val[2][1];
tr[u].lzy[0]=0,tr[u].lzy[1]=1,tr[u].lzy[2]=2;
}
void build(int u,int l,int r){
tr[u].l=l,tr[u].r=r;
tr[u].lzy[0]=0,tr[u].lzy[1]=1,tr[u].lzy[2]=2;
if(l==r){
tr[u].cnt[a[l]]=1;
return;
}
int mid=l+r>>1;
build(u<<1,l,mid);
build(u<<1|1,mid+1,r);
pushup(u);
}
struct Query{ll nxd;int cnt0,cnt1,cnt2;};
Query query(int u,int l,int r){
if(l<=tr[u].l&&tr[u].r<=r) return {tr[u].nxd,tr[u].cnt[0],tr[u].cnt[1],tr[u].cnt[2]};
pushdown(u);
int mid=tr[u].l+tr[u].r>>1;
if(l>mid) return query(u<<1|1,l,r);
else if(r<=mid) return query(u<<1,l,r);
else{
auto L=query(u<<1,l,r);
auto R=query(u<<1|1,l,r);
return {L.nxd+R.nxd+1ll*L.cnt1*R.cnt0+1ll*L.cnt2*R.cnt0+1ll*L.cnt2*R.cnt1,L.cnt0+R.cnt0,L.cnt1+R.cnt1,L.cnt2+R.cnt2};
}
}
void modify(int u,int l,int r,int s,int t,int v){
if(l<=tr[u].l&&tr[u].r<=r){
tr[u].lzy[0]=s,tr[u].lzy[1]=t,tr[u].lzy[2]=v;
int cnt[3];ll val[3][3];
memcpy(cnt,tr[u].cnt,sizeof tr[u].cnt);
memset(tr[u].cnt,0,sizeof tr[u].cnt);
for(int i=0;i<3;i++) tr[u].cnt[tr[u].lzy[i]]+=cnt[i];
memcpy(val,tr[u].val,sizeof tr[u].val);
memset(tr[u].val,0,sizeof tr[u].val);
for(int i=0;i<3;i++) for(int j=0;j<3;j++) if(i!=j) tr[u].val[tr[u].lzy[i]][tr[u].lzy[j]]+=val[i][j];
tr[u].nxd=tr[u].val[1][0]+tr[u].val[2][0]+tr[u].val[2][1];
return;
}
pushdown(u);
int mid=tr[u].l+tr[u].r>>1;
if(l<=mid) modify(u<<1,l,r,s,t,v);
if(mid<r) modify(u<<1|1,l,r,s,t,v);
pushup(u);
}
signed main(){
scanf("%lld%lld",&n,&q);
for(int i=1;i<=n;i++) scanf("%lld",a+i);
build(1,1,n);
for(int i=1,op,l,r,s,t,v;i<=q;i++){
scanf("%lld",&op);
if(op==1){
scanf("%lld%lld",&l,&r);
printf("%lld\n",query(1,l,r).nxd);
}
if(op==2){
scanf("%lld%lld%lld%lld%lld",&l,&r,&s,&t,&v);
modify(1,l,r,s,t,v);
}
}
return 0;
}