#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
const int N = 200010;
int n, m;
struct Node {
int l, r;
int sum, k;
int maxl, maxm, maxr;
} tr[N << 2];
void pushup(int u) {
tr[u].sum = tr[u << 1].sum + tr[u << 1 | 1].sum;
if(tr[u << 1].maxl == (tr[u << 1].r - tr[u << 1].l + 1))
tr[u].maxl = tr[u << 1].r - tr[u << 1].l + 1 + tr[u << 1 | 1].maxl;
else tr[u].maxl = tr[u << 1].maxl;
if(tr[u << 1 | 1].maxr == (tr[u << 1 | 1].r - tr[u << 1 | 1].l + 1))
tr[u].maxr = tr[u << 1 | 1].r - tr[u << 1 | 1].l + 1 + tr[u << 1].maxr;
else tr[u].maxr = tr[u << 1 | 1].maxr;
tr[u].maxm = max(max(tr[u << 1].maxm, tr[u << 1 | 1].maxm), tr[u << 1].maxr + tr[u << 1 | 1].maxl);
tr[u].maxm = max({tr[u].maxm, tr[u].maxl, tr[u].maxr});
}
void pushdown(int u) {
Node &root = tr[u], &L = tr[u << 1], &R = tr[u << 1 | 1];
if(root.k != -1) {
L.k = R.k = root.k;
L.sum = (L.r - L.l + 1) * root.k;
R.sum = (R.r - R.l + 1) * root.k;
L.maxl = L.maxm = L.maxr = (L.r - L.l + 1) * (root.k == 1 ? 0 : 1);
R.maxl = R.maxm = R.maxr = (R.r - R.l + 1) * (root.k == 1 ? 0 : 1);
root.k = -1;
}
}
void build(int u, int l, int r) {
if(l == r) tr[u] = {l, r, 1, -1, 0, 0, 0};
else {
tr[u] = {l, r, 0, -1, 0, 0, 0};
int Mid = (l + 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 y) {
if(l <= tr[u].l && tr[u].r <= r) {
tr[u].k = y;
tr[u].sum = (tr[u].r - tr[u].l + 1) * y;
tr[u].maxl = tr[u].maxm = tr[u].maxr = (tr[u].r - tr[u].l + 1) * (y == 1 ? 0 : 1);
} else {
pushdown(u);
int Mid = (tr[u].l + tr[u].r) >> 1;
if(l <= Mid) modify(u << 1, l, r, y);
if(Mid < r) modify(u << 1 | 1, l, r, y);
pushup(u);
}
}
int query1(int u, int l, int r) {
if(l <= tr[u].l && tr[u].r <= r) return tr[u].sum;
int Mid = (tr[u].l + tr[u].r) >> 1;
int sum = 0;
pushdown(u);
if(l <= Mid) sum += query1(u << 1, l, r);
if(Mid < r) sum += query1(u << 1 | 1, l, r);
return sum;
}
int query0(int u, int l, int r) {
if(l <= tr[u].l && tr[u].r <= r) return tr[u].r - tr[u].l + 1 - tr[u].sum;
int Mid = (tr[u].l + tr[u].r) >> 1;
int sum = 0;
pushdown(u);
if(l <= Mid) sum += query0(u << 1, l, r);
if(Mid < r) sum += query0(u << 1 | 1, l, r);
return sum;
}
int query2(int u, int l, int r) {
if(l <= tr[u].l && tr[u].r <= r) return tr[u].maxm;
int Mid = (tr[u].l + tr[u].r) >> 1;
int maxx = 0;
pushdown(u);
if(l <= Mid) maxx = max(maxx, query2(u << 1, l, r));
if(Mid < r) maxx = max(maxx, query2(u << 1 | 1, l, r));
return maxx;
}
void work(int l, int r, int l0, int r0) {
int x = query1(1, l, r);
if(x == 0) return ;
modify(1, l, r, 0);
int L = l0, R = r0 + 1;
while(L + 1 < R) {
int Mid = (L + R) / 2;
if(query0(1, l0, Mid) <= x) L = Mid;
else R = Mid;
}
modify(1, l0, L, 1);
}
int main() {
ios::sync_with_stdio(false);
cin.tie(0), cout.tie(0);
cin >> n >> m;
build(1, 1, n);
while(m --) {
int ops, l, r, l0, r0;
cin >> ops >> l >> r;
if(ops == 0) modify(1, l, r, 0);
else if(ops == 1) {
cin >> l0 >> r0;
work(l, r, l0, r0);
} else cout << query2(1, l, r) << '\n';
}
return 0;
}