#include <stdio.h>
typedef struct
{
int left, right, max;
int update;
} Node;
Node A[400000];
int maximum (int a, int b) {
if (a > b)
return a;
else
return b;
}
int minimum (int a, int b) {
if (a < b)
return a;
else
return b;
}
// ....[a.....(l......r)....b]....
int inclus (int l, int r, int a, int b) {
return a <= l && r <= b;
}
// ....(l.....[a......r)....b]....
int intersect (int l, int r, int a, int b) {
return l <= b && a <= r;
}
// update (1, 1, n, 2, 4, 5)
void update (int nod, int left, int right, int a, int b, int value) {
//printf ("Update nod = %d\t left = %d\t right = %d\t a = %d\t b = %d, value = %d, update = %d\n", nod, left, right, a, b, value, A[nod].update);
if (left == right) {
A[nod].left = minimum(1, value);
A[nod].right = minimum(1, value);
A[nod].max = minimum(1, value);
A[nod].update = 0;
return;
}
// update with flags when ppl leave or come
if (inclus (left, right, a, b)) {
if (value == 0) {
A[nod].left = 0;
A[nod].right = 0;
A[nod].max = 0;
A[nod].update = 1;
} else {
A[nod].left = right - left + 1;
A[nod].right = right - left + 1;
A[nod].max = right - left + 1;
A[nod].update = 1;
}
return;
}
int middle = (left + right) >> 1;
// Trebuie sa impingem valorile
if (A[nod].update == 1) {
A[nod].update = 0;
if (A[nod].max == 0) {
A[nod * 2].left = 0;
A[nod * 2].right = 0;
A[nod * 2].max = 0;
A[nod * 2].update = 1;
A[nod * 2 + 1].left = 0;
A[nod * 2 + 1].right = 0;
A[nod * 2 + 1].max = 0;
A[nod * 2 + 1].update = 1;
} else {
A[nod * 2].left = middle - left + 1;
A[nod * 2].right = middle - left + 1;
A[nod * 2].max = middle - left + 1;
A[nod * 2].update = 1;
A[nod * 2 + 1].left = right - middle;
A[nod * 2 + 1].right = right - middle;
A[nod * 2 + 1].max = right - middle;
A[nod * 2 + 1].update = 1;
}
}
if (intersect (left, middle, a, b))
update (nod * 2, left, middle, a, b, value);
if (intersect (middle + 1, right, a, b))
update (nod * 2 + 1, middle + 1, right, a, b, value);
// Update left
if (A[nod * 2].max == middle - left + 1) { // Daca left e full
A[nod].left = A[nod * 2].left + A[nod * 2 + 1].left;
} else { // Ramane cel de left
A[nod].left = A[nod * 2].left;
}
// Update right
if (A[nod * 2 + 1].max == right - middle) { // Daca right e full
A[nod].right = A[nod * 2 + 1].right + A[nod * 2].right;
} else { // Ramane cel de right
A[nod].right = A[nod * 2 + 1].right;
}
// Update max: este max_left sau max_right sau final_left + inceput_right
A[nod].max = maximum(maximum(A[nod * 2].max, A[nod * 2 + 1].max), A[nod * 2].right + A[nod * 2 + 1].left);
A[nod].update = 0;
}
int main() {
freopen ("hotel.in", "r", stdin);
freopen ("hotel.out", "w", stdout);
int n, m;
scanf ("%d %d", &n, &m);
int j;
for (j = 1; j <= n; ++j) {
update (1, 1, n, j, j, 1);
}
/*
for (j = 1; j <= 32; ++j)
printf ("Nod = %d,\t stg = %d,\t max = %d,\t dr = %d,\t update = %d\n",
j, A[j].left, A[j].max, A[j].right, A[j].update);
return 0;
*/
//update (1, 1, n, 1, n, n);
int i;
for (i = 0; i < m; ++i) {
int op;
scanf ("%d", &op);
if (op == 1) {
int left, right, add;
scanf ("%d %d", &left, &add);
right = left + add - 1;
update (1, 1, n, left, right, 0);
} else if (op == 2) {
int left, right, add;
scanf ("%d %d", &left, &add);
right = left + add - 1;
update (1, 1, n, left, right, add);
} else if (op == 3) {
printf ("%d\n", A[1].max);
}
/*
int j;
for (j = 1; j <= 32; ++j)
printf ("Nod = %d,\t stg = %d,\t max = %d,\t dr = %d,\t update = %d\n",
j, A[j].left, A[j].max, A[j].right, A[j].update);
*/
}
return 0;
}