#include <bits/stdc++.h>
#define LC tr[u << 1]
#define RC tr[u << 1 | 1]
#define PA tr[u]
#define LEN(TR) (TR.r - TR.l + 1)
using namespace std;
using ll = long long;
const int N = 1e5 + 10;
struct node_t {
int l, r;
int pre[2];
int suc[2];
int maxlen[2];
int sum, tag = -1;
} tr[4 * N];
int a[N];
void pushup(int u) {
PA.sum = LC.sum + RC.sum;
for (int i = 0; i < 2; ++i) {
PA.maxlen[i] = max(max(LC.maxlen[i], RC.maxlen[i]), LC.suc[i] + RC.pre[i]);
PA.pre[i] = LC.pre[i] == LEN(LC) ? LEN(LC) + RC.pre[i] : LC.pre[i];
PA.suc[i] = RC.suc[i] == LEN(RC) ? LEN(RC) + LC.suc[i] : RC.suc[i];
}
}
void update(int u, int op) {
switch (op) {
case 0:
PA.maxlen[1] = PA.sum = PA.pre[1] = PA.suc[1] = 0;
PA.maxlen[0] = PA.pre[0] = PA.suc[0] = LEN(PA);
break;
case 1:
PA.maxlen[1] = PA.pre[1] = PA.suc[1] = PA.sum = LEN(PA);
PA.maxlen[0] = PA.pre[0] = PA.suc[0] = 0;
break;
case 2:
PA.sum = LEN(PA) - PA.sum;
swap(PA.pre[0], PA.pre[1]);
swap(PA.suc[0], PA.suc[1]);
swap(PA.maxlen[0], PA.maxlen[1]);
}
}
void fix_tag(int u, int op) {
switch (op) {
case -1:
return;
case 0:
case 1:
PA.tag = op;
break;
case 2:
if (PA.tag == 0 || PA.tag == 1)
PA.tag = !PA.tag;
else if (PA.tag == -1)
PA.tag = op;
else
PA.tag = -1;
}
}
void pushdown(int u) {
if (PA.tag == -1)
return;
fix_tag(u << 1, PA.tag);
update(u << 1, LC.tag);
fix_tag(u << 1 | 1, PA.tag);
update(u << 1 | 1, RC.tag);
PA.tag = -1;
}
void build(int u, int l, int r) {
PA.l = l, PA.r = r;
if (PA.l == PA.r) {
PA.maxlen[1] = PA.sum = a[l] = PA.pre[1] = PA.suc[1] = a[l];
PA.maxlen[0] = PA.pre[0] = PA.suc[0] = !a[l];
}
else {
int mid = PA.l + PA.r >> 1;
build(u << 1, l, mid);
build(u << 1 | 1, mid + 1, r);
pushup(u);
}
}
void modify(int u, int l, int r, int op) {
if (l <= PA.l && PA.r <= r) {
update(u, op);
fix_tag(u, op);
}
else {
pushdown(u);
int mid = PA.l + PA.r >> 1;
if (l <= mid)
modify(u << 1, l, r, op);
if (mid < r)
modify(u << 1 | 1, l, r, op);
pushup(u);
}
}
int query(int u, int l, int r, int op) {
if (l <= PA.l && PA.r <= r)
return op == 3 ? PA.sum : PA.maxlen[1];
int mid = PA.l + PA.r >> 1;
int ans = 0;
pushdown(u);
if (l <= mid)
ans = query(u << 1, l, r, op);
if (mid < r)
ans += query(u << 1 | 1, l, r, op);
return ans;
}
int main() {
#ifndef ONLINE_JUDGE
freopen(".in", "r", stdin);
#endif
ios::sync_with_stdio(false);
cin.tie(0);
int n, m;
cin >> n >> m;
for (int i = 1; i <= n; ++i)
cin >> a[i];
build(1, 1, n);
while (m--) {
int op, l, r;
cin >> op >> l >> r;
++l, ++r;
if (op <= 2)
modify(1, l, r, op);
else
cout << query(1, l, r, op) << "\n";
}
}