#include <bits/stdc++.h>
using namespace std;
const int N = 2000010;
int n, m;
struct SegmentTree {
int l, r, ml, mr, sum0, sum1;
int lazy_tag = -1;
int Max;
} tr[N << 2];
void up(int k) {
tr[k].sum0 = tr[k << 1].sum0 + tr[k << 1 | 1].sum0;
tr[k].sum1 = tr[k << 1].sum1 + tr[k << 1 | 1].sum1;
tr[k].Max = max({
tr[k << 1].Max,
tr[k << 1 | 1].Max,
tr[k << 1].mr + tr[k << 1 | 1].ml
});
tr[k].ml = (tr[k << 1].ml == tr[k << 1].r - tr[k << 1].l + 1 ? tr[k << 1].ml + tr[k << 1 | 1].ml : tr[k << 1].ml);
tr[k].mr = (tr[k << 1 | 1].mr == tr[k << 1 | 1].r - tr[k << 1 | 1].l + 1 ? tr[k << 1 | 1].mr + tr[k << 1].mr : tr[k << 1 | 1].mr);
}
void Build(int k, int l, int r) {
tr[k].l = l, tr[k].r = r;
if (l == r) {
tr[k].sum0 = 0, tr[k].sum1 = 1;
tr[k].lazy_tag = -1;
return ;
}
int mid = l + r >> 1;
Build(k << 1, l, mid);
Build(k << 1 | 1, mid + 1, r);
up(k);
}
void down(int k) {
if (tr[k].lazy_tag != -1) {
tr[k << 1].lazy_tag = tr[k].lazy_tag;
tr[k << 1 | 1].lazy_tag = tr[k].lazy_tag;
if (tr[k].lazy_tag == 0) {
tr[k << 1].sum0 = tr[k << 1].r - tr[k << 1].l + 1;
tr[k << 1].sum1 = 0;
tr[k << 1 | 1].sum0 = tr[k << 1 | 1].r - tr[k << 1 | 1].l + 1;
tr[k << 1 | 1].sum1 = 0;
tr[k << 1].ml = tr[k << 1].mr = tr[k << 1].sum0;
tr[k << 1 | 1].ml = tr[k << 1 | 1].mr = tr[k << 1 | 1].sum0;
} else {
tr[k << 1].sum0 = 0;
tr[k << 1].sum1 = tr[k << 1].r - tr[k << 1].l + 1;
tr[k << 1 | 1].sum0 = 0;
tr[k << 1 | 1].sum1 = tr[k << 1 | 1].r - tr[k << 1 | 1].l + 1;
tr[k << 1].ml = tr[k << 1].mr = 0;
tr[k << 1 | 1].ml = tr[k << 1 | 1].mr = 0;
}
tr[k].lazy_tag = -1;
}
}
void Updata(int k, int l, int r, int val) {
if (tr[k].l > r || tr[k].r < l) return ;
if (l <= tr[k].l && tr[k].r <= r) {
tr[k].lazy_tag = val;
if (val == 0) tr[k].sum0 = tr[k].r - tr[k].l + 1, tr[k].sum1 = 0, tr[k].ml = tr[k].mr = tr[k].sum0;
else tr[k].sum0 = 0, tr[k].sum1 = tr[k].r - tr[k].l + 1, tr[k].ml = tr[k].mr = 0;
return ;
}
down(k);
Updata(k << 1, l, r, val);
Updata(k << 1 | 1, l, r, val);
up(k);
}
int Query(int k, int l, int r, int val) {
if (tr[k].l > r || tr[k].r < l) return 0;
if (l <= tr[k].l && tr[k].r <= r) {
if (val == 0) return tr[k].sum0;
else return tr[k].sum1;
}
down(k);
return Query(k << 1, l, r, val) + Query(k << 1 | 1, l, r, val);
}
int Query(int k, int x) {
if (tr[k].l == tr[k].r) return tr[k].l;
down(k);
if (x <= tr[k << 1].sum0) return Query(k << 1, x);
else return Query(k << 1 | 1, x - tr[k << 1].sum0);
}
SegmentTree Query(int k, int l, int r) {
if (tr[k].l > r || tr[k].r < l) return {0, 0, 0, 0, 0, 0, 0, 0};
if (l <= tr[k].l && tr[k].r <= r) return tr[k];
down(k);
SegmentTree t1 = Query(k << 1, l, r);
SegmentTree t2 = Query(k << 1 | 1, l, r);
SegmentTree t3 = {
0, 0,
(t1.ml == t1.r - t1.l + 1 ? t1.ml + t2.ml : t1.ml),
(t2.mr == t2.r - t2.l + 1 ? t1.mr + t2.mr : t2.mr),
t1.sum0 + t2.sum0,
t1.sum1 + t2.sum1,
0,
max({
t1.Max,
t2.Max,
t1.mr + t2.ml
})
};
return t3;
}
signed main() {
cin >> n >> m;
Build(1, 1, n);
while (m -- ) {
int op, l, r, L, R;
cin >> op >> l >> r;
if (op == 0) {
Updata(1, l, r, 0);
} else if (op == 1) {
cin >> L >> R;
int t1 = Query(1, l, r, 1);
int t2 = Query(1, L, R, 0);
Updata(1, l, r, 0);
if (t1 >= t2) {
Updata(1, L, R, 1);
continue;
}
int t3 = Query(1, 1, L - 1, 0);
t3 += t1;
int t4 = Query(1, t3);
Updata(1, L, t4, 1);
} else {
cout << Query(1, l, r).Max << "\n";
}
}
return 0;
}