#include <bits/stdc++.h>
using namespace std;
const int N = 2e5 + 5;
struct node
{
int l, r, sum, lmax, rmax, tag, maxi;
} tree[N << 2];
inline int getlen(int x)
{
return tree[x].r - tree[x].l + 1;
}
void pushup(int x)
{
tree[x].sum = tree[x << 1].sum + tree[x << 1 | 1].sum;
if(getlen(x << 1) == tree[x << 1].lmax)
tree[x].lmax = getlen(x << 1) + tree[x << 1 | 1].lmax;
else tree[x].lmax = tree[x << 1].lmax;
if(getlen(x << 1 | 1) == tree[x << 1 | 1].rmax)
tree[x].rmax = getlen(x << 1 | 1) + tree[x << 1].rmax;
else tree[x].rmax = tree[x << 1 | 1].rmax;
tree[x].maxi = max(max(tree[x << 1].maxi, tree[x << 1 | 1].maxi), tree[x << 1].rmax + tree[x << 1 | 1].lmax);
return;
}
void pushdown(int x)
{
if(!tree[x].tag) return;
tree[x << 1].tag = tree[x << 1 | 1].tag = tree[x].tag;
if(tree[x].tag == 1)
{
tree[x << 1].maxi = tree[x << 1].lmax = tree[x << 1].rmax = getlen(x << 1);
tree[x << 1 | 1].maxi = tree[x << 1 | 1].lmax = tree[x << 1 | 1].rmax = getlen(x << 1 | 1);
tree[x << 1].sum = tree[x << 1 | 1].sum = 0;
}
else
{
tree[x << 1].maxi = tree[x << 1].lmax = tree[x << 1].rmax = 0;
tree[x << 1 | 1].maxi = tree[x << 1 | 1].lmax = tree[x << 1 | 1].rmax = 0;
tree[x << 1].sum = getlen(x << 1), tree[x << 1 | 1].sum = getlen(x << 1 | 1);
}
tree[x].tag = 0;
}
void build(int l, int r, int x)
{
tree[x] = {l, r, 0, 0, 0, 0, 0};
if(l == r) return (void) (tree[x].sum = 1, tree[x].maxi = tree[x].lmax = tree[x].rmax = 0);
int mid = (l + r) >> 1;
build(l, mid, x << 1);
build(mid + 1, r, x << 1 | 1);
pushup(x);
return;
}
void update(int l, int r, int k, int x)
{
if(l <= tree[x].l && tree[x].r <= r)
{
tree[x].tag = k;
if(k == 1) tree[x].maxi = tree[x].lmax = tree[x].rmax = getlen(x), tree[x].sum = 0;
else tree[x].maxi = tree[x].lmax = tree[x].rmax = 0, tree[x].sum = getlen(x);
return;
}
int mid = (tree[x].l + tree[x].r) >> 1;
pushdown(x);
if(l <= mid) update(l, r, k, x << 1);
if(mid < r) update(l, r, k, x << 1 | 1);
pushup(x);
return;
}
int query_sum(int l, int r, int x)
{
if(l <= tree[x].l && tree[x].r <= r) return tree[x].sum;
int mid = (tree[x].l + tree[x].r) >> 1, ans = 0;
pushdown(x);
if(l <= mid) ans += query_sum(l, r, x << 1);
if(mid < r) ans += query_sum(l, r, x << 1 | 1);
return ans;
}
int query_max(int l, int r, int x)
{
if(l <= tree[x].l && tree[x].r <= r) return tree[x].maxi;
int mid = (tree[x].l + tree[x].r) >> 1;
int ans = min(tree[x << 1].rmax, tree[x << 1 | 1].l - l) + min(tree[x << 1 | 1].lmax, r - tree[x << 1].r);
pushdown(x);
if(r < tree[x << 1 | 1].l) return query_max(l, r, x << 1);
else if(l > tree[x << 1].r) return query_max(l, r, x << 1 | 1);
else ans = max(ans, max(query_max(l, r, x << 1), query_max(l, r, x << 1 | 1)));
return ans;
}
int change(int l, int r, int k, int x)
{
if(!k) return 0;
if(l <= tree[x].l && tree[x].r <= r && tree[x].sum <= k)
{
int ss = tree[x].sum;
tree[x].maxi = tree[x].lmax = tree[x].rmax = 0;
tree[x].sum = getlen(x), tree[x].tag = 2;
return k - ss;
}
int mid = (tree[x].l + tree[x].r) >> 1, ans = 0;
pushdown(x);
if(r < tree[x << 1 | 1].l) ans = change(l, r, k, x << 1);
else if(l > tree[x << 1].r) ans = change(l, r, k, x << 1 | 1);
else ans = change(l, r, change(l, r, k, x << 1), x << 1 | 1);
pushup(x);
return ans;
}
int n, m, opt, l, r, l0, r0, l1, r1;
int main()
{
ios :: sync_with_stdio(false);
cin.tie(0), cout.tie(0);
cin >> n >> m;
build(1, n, 1);
while(m--)
{
cin >> opt;
if(opt == 0)
{
cin >> l >> r;
update(l, r, 1, 1);
}
else if(opt == 1)
{
cin >> l0 >> r0 >> l1 >> r1;
int s = query_sum(l0, r0, 1), L = l1, R = r1, c = l1;
if(!s) continue;
update(l0, r0, 1, 1);
while(L <= R)
{
int mid = (L + R) >> 1;
if(mid - l1 + 1 - query_sum(l1, mid, 1) <= s) c = mid, L = mid + 1;
else R = mid - 1;
}
update(l1, c, 2, 1);
}
else
{
cin >> l >> r;
cout << query_max(l, r, 1) << '\n';
}
}
return 0;
}