#include <iostream>
#include <fstream>
#include <algorithm>
#define fiu1 (nod << 1)
#define fiu2 (fiu1 + 1)
#define mid ((st + dr) >> 1)
using namespace std;
ifstream fin("hotel.in");
ofstream fout("hotel.out");
const int Nmax = 100010;
struct snod{
int a, b, c;
snod(){a = b = c = 0;}
}arb[Nmax * 3 + 100];
int N, P;
void BuildTree(int nod, int st, int dr)
{
arb[nod].a = arb[nod].b = arb[nod].c = dr - st + 1;
if(st == dr) return;
BuildTree(fiu1, st, mid);
BuildTree(fiu2, mid + 1, dr);
}
void Update_Sons(int nod, int st, int dr)
{
if(arb[nod].c == dr - st + 1)
{
arb[fiu1].a = arb[fiu1].b = arb[fiu1].c = mid - st + 1;
arb[fiu2].a = arb[fiu2].b = arb[fiu2].c = dr - mid;
}else
if(!arb[nod].c)
{
arb[fiu1].a = arb[fiu1].b = arb[fiu1].c = 0;
arb[fiu2].a = arb[fiu2].b = arb[fiu2].c = 0;
}
}
void Update(int nod, int st, int dr, int left, int right, bool tip)
{
if(st > right || dr < left) return;
if(st != dr) Update_Sons(nod, st, dr);
if(left <= st && dr <= right)
{
int add = tip == 0 ? 0 : dr - st + 1;
arb[nod].a = arb[nod].b = arb[nod].c = add;
return;
}
if(st == dr) return;
Update(fiu1, st, mid, left, right, tip);
Update(fiu2, mid + 1, dr, left, right, tip);
arb[nod].a = arb[fiu1].a;
if(arb[fiu1].a == mid - st + 1)
arb[nod].a += arb[fiu2].a;
arb[nod].b = arb[fiu2].b;
if(arb[fiu2].b == dr - mid)
arb[nod].b += arb[fiu1].b;
arb[nod].c = arb[fiu1].b + arb[fiu2].a;
arb[nod].c = max(max(arb[nod].c, arb[nod].a), arb[nod].b);
arb[nod].c = max(max(arb[nod].c, arb[fiu1].c), arb[fiu2].c);
}
int main()
{
fin>>N>>P;
BuildTree(1, 1, N);
for(int tip, left, right; P; P--)
{
fin>>tip;
if(tip == 1)
{
fin>>left>>right;
Update(1, 1, N, left, left + right - 1, 0);
}
else if(tip == 2)
{
fin>>left>>right;
Update(1, 1, N, left, left + right - 1, 1);
}
else
fout<<arb[1].c<<'\n';
}
return 0;
}