#include <bits/stdc++.h>
using namespace std;
int n;
struct
{
int lazy, best, st, dr;
} arb[265000];
void updateNode(int nod, int st, int dr)
{
if(arb[nod].lazy != -1)
{
if(st != dr)
{
arb[nod * 2].lazy = arb[nod].lazy;
arb[nod * 2 + 1].lazy = arb[nod].lazy;
}
if(arb[nod].lazy == 0)
arb[nod].best = arb[nod].st = arb[nod].dr = dr - st + 1;
else arb[nod].best = arb[nod].st = arb[nod].dr = 0;
arb[nod].lazy = -1;
}
}
int ist, idr;
void update(int nod, int st, int dr, int val)
{
updateNode(nod, st, dr);
if(st >= ist && dr <= idr)
{
arb[nod].lazy = val;
updateNode(nod, st, dr);
return;
}
int mij = (st + dr) / 2;
if(mij >= ist)
update(nod * 2, st, mij, val);
else updateNode(nod * 2, st, mij);
if(mij < idr)
update(nod * 2 + 1, mij + 1, dr, val);
else updateNode(nod * 2 + 1, mij + 1, dr);
int lgst = mij - st + 1;
int lgdr = dr - mij;
if(arb[nod * 2].st == lgst)
arb[nod].st = lgst + arb[nod * 2 + 1].st;
else arb[nod].st = arb[nod * 2].st;
if(arb[nod * 2 + 1].dr == lgdr)
arb[nod].dr = lgdr + arb[nod * 2].dr;
else arb[nod].dr = arb[nod * 2 + 1].dr;
arb[nod].best = max(arb[nod * 2].best, arb[nod * 2 + 1].best);
arb[nod].best = max(arb[nod].best, arb[nod * 2].dr + arb[nod * 2 + 1].st);
}
void build(int nod, int st, int dr)
{
if(st != dr)
{
int mij = (st + dr) / 2;
build(nod * 2, st, mij);
build(nod * 2 + 1, mij + 1, dr);
}
arb[nod].best = arb[nod].st = arb[nod].dr = dr - st + 1;
arb[nod].lazy = -1;
}
int main()
{
freopen("hotel.in", "r", stdin);
freopen("hotel.out", "w", stdout);
int q;
scanf("%d%d", &n, &q);
build(1, 1, n);
while(q--)
{
int c, m, i;
scanf("%d", &c);
if(c == 1)
{
scanf("%d%d", &i, &m);
ist = i;
idr = i + m - 1;
update(1, 1, n, 1);
}
else if(c == 2)
{
scanf("%d%d", &i, &m);
ist = i;
idr = i + m - 1;
update(1, 1, n, 0);
}
else
{
printf("%d\n", arb[1].best);
}
}
return 0;
}