#include <bits/stdc++.h>
#define N 100000
using namespace std;
int n, p, i, cerinta, l, r;
struct interval
{
int st, dr, sol, lazy;
};
interval Arbore[4*N+5];
void initializare (int nod, int a, int b)
{
Arbore[nod].st=Arbore[nod].dr=Arbore[nod].sol=b-a+1;
if(a==b)
return;
int mid=(a+b)/2;
initializare (2*nod, a, mid);
initializare (2*nod+1, mid+1, b);
}
void propag (int nod, int a, int b)
{
//nimic de propagat
if(Arbore[nod].lazy==0)
return;
//se elibereaza un interval de camere
if(Arbore[nod].lazy==2)
Arbore[nod].st=Arbore[nod].dr=Arbore[nod].sol=b-a+1;
else //se ocupa un interval de camere
if(Arbore[nod].lazy==1)
Arbore[nod].st=Arbore[nod].dr=Arbore[nod].sol=0;
if(a<b)
Arbore[2*nod].lazy=Arbore[2*nod+1].lazy=Arbore[nod].lazy;
Arbore[nod].lazy=0;
}
void update (int nod, int val, int a, int b, int ua, int ub)
{
if(ua<=a && b<=ub)
{
Arbore[nod].lazy=val;
propag(nod, a, b);
return;
}
propag(nod, a, b);
int mid=(a+b)/2;
if(ua<=mid)
update(2*nod, val, a, mid, ua, ub);
else propag(2*nod, a, mid);
if(ub>mid)
update(2*nod+1, val, mid+1, b, ua, ub);
else propag(2*nod+1, mid+1, b);
Arbore[nod].sol=max((Arbore[2*nod].dr + Arbore[2*nod+1].st), max(Arbore[2*nod].sol, Arbore[2*nod+1].sol));
//pe stanga
Arbore[nod].st=Arbore[2*nod].st;
if(Arbore[nod].st==mid-a+1)
Arbore[nod].st+=Arbore[2*nod+1].st;
//pe dreapta
Arbore[nod].dr=Arbore[2*nod+1].dr;
if(Arbore[nod].dr==b-mid)
Arbore[nod].dr+=Arbore[2*nod].dr;
}
int main()
{
freopen("hotel.in", "r", stdin);
freopen("hotel.out", "w", stdout);
scanf("%d%d", &n, &p);
initializare(1, 1, n);
for(i=1; i<=p; i++)
{
scanf("%d", &cerinta);
if(cerinta==3)
{
propag(1, 1, n);
printf("%d\n", Arbore[1].sol);
}
else
{
scanf("%d%d", &l, &r);
r+=l-1;
update(1, cerinta, 1, n, l, r);
}
}
return 0;
}