#include <fstream>
#include <algorithm>
#include <vector>
#include <math.h>
#include <stdlib.h>
using namespace std;
const int dim = 100005;
int N, M, nodinterior, nodmargin1, nodmargin2, tip;
int pozs, pozd, pozsupdate, pozdupdate, valupdate, pozq, lg, index;
int H[dim], PH[dim * 2], PS[dim * 2], PD[dim * 2], AI[dim * 4];
void destroy (int nh);
void shrink_right (int nh);
void shrink_left (int nh);
void split (int nh);
int create ();
int xpand_right (int nh);
int expand_left (int nh);
int merge (int nh1, int nh2);
void modifica_interval (int nh);
bool cmpheap (int n1, int n2)
{
return PD[H[n1]] - PS[H[n1]] > PD[H[n2]] - PS[H[n2]];
}
void upheap (int n)
{
int t = n >> 1;
while (t != 0 && cmpheap (n, t))
{
swap (H[n], H[t]);
swap (PH[n], PH[t]);
n = t;
t = n >> 1;
}
}
void downheap (int n)
{
int f = n << 1;
if (f+1 <= H[0] && cmpheap (f+1, f)) f++;
while (f <= H[0] && cmpheap (f, n))
{
swap (H[n], H[f]);
swap (PH[n], PH[f]);
n = f;
f = n << 1;
if (f+1 <= H[0] && cmpheap (f+1, f)) f++;
}
}
void initializari ()
{
index = 1;
for (int i = 1; i < dim; i++)
{
PS[i] = PD[i] = -1;
AI[i] = 1;
}
H[H[0] = 1] = 1;
PH[1] = 1;
PS[1] = 1;
PD[1] = N;
}
void update (int nod, int st, int dr)
{
if (nod > 1 && AI[nod >> 1] != -1)
AI[nod] = AI[nod >> 1];
if (pozdupdate < st || dr < pozsupdate)
return;
if (pozsupdate <= st && dr <= pozdupdate)
{
AI[nod] = valupdate;
return;
}
int m = (st + dr) >> 1;
int f1 = nod << 1;
int f2 = f1 + 1;
update (f1, st, m);
update (f2, m + 1, dr);
if (AI[f1] == AI[f2])
AI[nod] = AI[f1];
else
AI[nod] = -1;
}
int query (int nod, int st, int dr)
{
if (nod > 1 && AI[nod >> 1] != -1)
AI[nod] = AI[nod >> 1];
if (pozq < st || dr < pozq)
return 0;
if (pozq == st && pozq == dr)
{
return nod;
}
int m = (st + dr) >> 1, ok = 0;
int f1 = nod << 1;
int f2 = f1 + 1;
ok = ok | query (f1, st, m);
ok = ok | query (f2, m + 1, dr);
if (AI[f1] == AI[f2])
AI[nod] = AI[f1];
else
AI[nod] = -1;
return ok;
}
void citeste ()
{
scanf ("%d%d", &pozs, &lg);
pozd = pozs + lg - 1;
pozq = pozs - 1;
nodmargin1 = pozs == 1 ? 0 : query (1, 1, N);
pozq = pozd + 1;
nodmargin2 = pozd == N ? 0 : query (1, 1, N);
if (tip == 1)
{
pozq = pozs;
nodinterior = query (1, 1, N);
}
}
void destroy (int nh)
{
//elimina elementul nh din heap
int n = H[H[0]--];
PH[n] = PH[nh];
H[PH[n]] = n;
upheap (PH[n]);
downheap (PH[n]);
}
void shrink_right (int nh)
{
//elimina o bucata din stanga elemntului nh din heap aflat la dreapta intervalului citit
PS[nh] = pozd + 1;
upheap (PH[nh]);
downheap (PH[nh]);
modifica_interval (nh);
}
void shrink_left (int nh)
{
//elimina o bucata din dreapta elementului nh din heap aflat la stanga intervalului citit
PD[nh] = pozs - 1;
upheap (PH[nh]);
downheap (PH[nh]);
modifica_interval (nh);
}
void split (int nh)
{
//nodul nh din heap se va imparti in nodul nh care se termina la capatul stanga
//al intervalului citit si nodul nh2 care incepe la capatul din dreapta intervalului citit
int nh2 = ++index;
H[++H[0]] = nh2;
PH[nh2] = H[0];
PS[nh2] = PS[nh];
PD[nh2] = PD[nh];
shrink_left (nh);
shrink_right (nh2);
}
int create ()
{
//creeaza elementul din heap nh pe intervalul citit
int nh = ++index;
H[++H[0]] = nh;
PH[nh] = H[0];
PS[nh] = pozs;
PD[nh] = pozd;
upheap (PH[nh]);
downheap (PH[nh]);
modifica_interval (nh);
return nh;
}
int xpand_right (int nh)
{
//expandez catre stanga elementul nh din heap aflat in dreapta intervalului curent
PS[nh] = pozs;
upheap (PH[nh]);
downheap (PH[nh]);
modifica_interval (nh);
return nh;
}
int xpand_left (int nh)
{
//expandez catre dreapta elementul nh din heap situat la stanga intervalului curent
PD[nh] = pozd;
upheap (PH[nh]);
downheap (PH[nh]);
modifica_interval (nh);
return nh;
}
int merge (int nh1, int nh2)
{
//unesc elementele din heap nh1 si nh2
//reuniunea lor va fi nh1 iar pe nh2 il distrug
PD[nh1] = PD[nh2];
destroy (nh2);
modifica_interval (nh1);
return nh1;
}
void modifica_interval (int nh)
{
pozsupdate = PS[nh];
pozdupdate = PD[nh];
valupdate = nh;
update (1, 1, N);
}
int main ()
{
freopen ("hotel.in", "r", stdin);
freopen ("hotel.out", "w", stdout);
scanf ("%d%d", &N, &M);
initializari ();
while (M --)
{
scanf ("%d", &tip);
if (tip == 1)
{
citeste ();
if (AI[nodmargin1] == 0 && AI[nodmargin1] == 0)
{
destroy (AI[nodinterior]);
}
else if (AI[nodmargin1] == 0)
{
shrink_right (AI[nodmargin2]);
}
else if (AI[nodmargin2] == 0)
{
shrink_left (AI[nodmargin1]);
}
else
{
split (AI[nodinterior]);
}
pozsupdate = pozs;
pozdupdate = pozd;
valupdate = 0;
update (1, 1, N);
}
else if (tip == 2)
{
citeste ();
if (AI[nodmargin1] == 0 && AI[nodmargin1] == 0)
{
nodinterior = create ();
}
else if (AI[nodmargin1] == 0)
{
nodinterior = xpand_right (AI[nodmargin2]);
}
else if (AI[nodmargin2] == 0)
{
nodinterior = xpand_left (AI[nodmargin1]);
}
else
{
nodinterior = merge (AI[nodmargin1], AI[nodmargin2]);
}
update (1, 1, N);
}
else
{
printf ("%d\n", PD[H[1]] - PS[H[1]] + 1);
}
}
return 0;
}