#include <fstream>
#include <vector>
#include <algorithm>
using namespace std;
class ST {
public:
ST( int _N )
{
N = _N;
T = D = S = vector<int>(4 * N);
lz = vector<int>(4 * N);
Build(1, 1, N);
}
void Update(int x, int y, int v)
{
Update(1, 1, N, x, y, v);
}
int Query() const
{
return T[1];
}
protected:
void Build( int nod, int st, int dr )
{
T[nod] = S[nod] = D[nod] = dr - st + 1;
if (st == dr) return;
int m = (st + dr) / 2;
Build(2 * nod, st, m);
Build(2 * nod + 1, m + 1, dr);
}
void PushDown(int nod, int st, int dr)
{
if (lz[nod])
{
if (T[nod] == 0)
T[nod] = S[nod] = D[nod] = (dr - st + 1);
else
T[nod] = S[nod] = D[nod] = 0;
if (st != dr)
{
lz[2 * nod] ^= lz[nod];
lz[2 * nod + 1] ^= lz[nod];
}
lz[nod] = 0;
}
}
void Update(int nod, int st, int dr, int L, int R, int val)
{
PushDown(nod, st, dr);
if (L <= st && dr <= R)
{
lz[nod] ^= 1;
PushDown(nod, st, dr);
return;
}
if (st > dr || st > R || dr < L) return;
int m = (st + dr) / 2;
Update(2 * nod, st, m, L, R, val);
Update(2 * nod + 1, m + 1, dr, L, R, val);
S[nod] = S[2 * nod];
if (S[2 * nod] == m - st + 1)
S[nod] += S[2 * nod + 1];
D[nod] = D[2 * nod + 1];
if (D[2 * nod + 1] == dr - m)
D[nod] += D[2 * nod];
T[nod] = max({T[2 * nod], T[2 * nod + 1], D[2 * nod] + S[2 * nod + 1]});
}
private:
vector<int> T, D, S; // Maxim din tot, maxim la stanga, maxim la dreapta
vector<int> lz;
int N;
};
int n, m, op, i, L;
int main()
{
ifstream fin("hotel.in");
ofstream fout("hotel.out");
fin >> n >> m;
ST s(n);
while ( m-- )
{
fin >> op;
if (op == 1)
{
fin >> i >> L;
s.Update(i, i + L - 1, 0);
}
if ( op == 2 )
{
fin >> i >> L;
s.Update(i, i + L - 1, 1);
}
if ( op == 3 )
fout << s.Query() << "\n";
}
return 0;
}