#include<iostream>
#include<algorithm>
const int sz = 1e5 + 10;
int arr[sz];
struct ST {
struct node {
int sum1, maxs1, maxl1, maxr1, sum0, maxs0, maxl0, maxr0;
node operator+(const node &a) const {
return node {
sum1 + a.sum1,
std::max(std::max(maxs1, a.maxs1), maxr1 + a.maxl1),
maxl1 + (sum0 == 0) * a.maxl1,
(a.sum0 == 0) * maxr1 + a.maxr1,
sum0 + a.sum0,
std::max(std::max(maxs0, a.maxs0), maxr0 + a.maxl0),
maxl0 + (sum1 == 0) * a.maxl0,
(a.sum1 == 0) * maxr0 + a.maxr0,
};
}
} tree[sz << 2];
bool iscov[sz << 2], isreverse[sz << 2];
int cov[sz << 2];
void operationAssign(int p, int ln, int rn, int val) {
int l = rn - ln + 1;
isreverse[p] = 0;
cov[p] = val, iscov[p] = 1;
if (val == 0)
tree[p] = {0, 0, 0, 0, l, l, l, l};
else tree[p] = {l, l, l, l, 0, 0, 0, 0};
}
void operationReverse(int p) {
if (iscov[p]) return cov[p] ^= 1, void();
std::swap(tree[p].sum0, tree[p].sum1);
std::swap(tree[p].maxs0, tree[p].maxs1);
std::swap(tree[p].maxl0, tree[p].maxl1);
std::swap(tree[p].maxr0, tree[p].maxr1);
isreverse[p] ^= 1;
}
void pushdown(int p, int ln, int rn) {
if (iscov[p]) {
int mid = ln + rn >> 1;
operationAssign(p << 1, ln, mid, cov[p]);
operationAssign(p << 1 | 1, mid + 1, rn, cov[p]);
iscov[p] = 0;
}
if (isreverse[p])
operationReverse(p << 1), operationReverse(p << 1 | 1), isreverse[p] = 0;
}
void build(int p, int ln, int rn) {
if (ln == rn)
return tree[p] = node{arr[ln] == 1, arr[ln] == 1, arr[ln] == 1, arr[ln] == 1,
arr[ln] == 0, arr[ln] == 0, arr[ln] == 0, arr[ln] == 0}, void();
int mid = ln + rn >> 1;
build(p << 1, ln, mid);
build(p << 1 | 1, mid + 1, rn);
tree[p] = tree[p << 1] + tree[p << 1 | 1];
}
void assign(int p, int ln, int rn, int l, int r, int val) {
if (ln >= l && rn <= r) return operationAssign(p, ln, rn, val);
if (ln > r || rn < l) return;
int mid = ln + rn >> 1;
pushdown(p, ln, rn);
assign(p << 1, ln, mid, l, r, val);
assign(p << 1 | 1, mid + 1, rn, l, r, val);
tree[p] = tree[p << 1] + tree[p << 1 | 1];
}
void reverse(int p, int ln, int rn, int l, int r) {
if (ln >= l && rn <= r) return operationReverse(p);
if (ln > r || rn < l) return;
int mid = ln + rn >> 1;
pushdown(p, ln, rn);
reverse(p << 1, ln, mid, l, r);
reverse(p << 1 | 1, mid + 1, rn, l, r);
tree[p] = tree[p << 1] + tree[p << 1 | 1];
}
node query(int p, int ln, int rn, int l, int r) {
if (ln >= l && rn <= r) return tree[p];
if (ln > r || rn < l) return node{0, 0, 0, 0, 0, 0, 0, 0};
int mid = ln + rn >> 1;
pushdown(p, ln, rn);
node res = node{0, 0, 0, 0, 0, 0, 0, 0};
res = res + query(p << 1, ln, mid, l, r);
res = res + query(p << 1 | 1, mid + 1, rn, l, r);
return res;
}
} st;
int main() {
std::ios::sync_with_stdio(false);
std::cin.tie(nullptr);
int n, m;
std::cin >> n >> m;
for (int i = 1; i <= n; i++) std::cin >> arr[i];
st.build(1, 1, n);
while (m--) {
int op, l, r;
std::cin >> op >> l >> r;
l++, r++;
if (op == 0) st.assign(1, 1, n, l, r, 0);
if (op == 1) st.assign(1, 1, n, l, r, 1);
if (op == 2) st.reverse(1, 1, n, l, r);
if (op == 3) std::cout << st.query(1, 1, n, l, r).sum1 << "\n";
if (op == 4) std::cout << st.query(1, 1, n, l, r).maxs1 << "\n";
}
return 0;
}