#include <fstream>
#include <bits/stdc++.h>
#include <iostream>
#define N 100005
using namespace std;
ifstream fin("hotel.in");
ofstream fout("hotel.out");
struct Segtree{
bool propagate;
int propWith;
int pref, suff, best;
int len;
}V[4 * N];
void build(int v, int l, int r) {
if (l == r) {
V[v].len = 1;
V[v].pref = V[v].suff = V[v].best = 1;
return;
}
int mij = (l + r) / 2;
build(v * 2, l, mij);
build(v * 2 + 1, mij + 1, r);
V[v].len = V[v * 2].len + V[v * 2 + 1].len;
V[v].pref = V[v].suff = V[v].best = V[v].len;
}
void apply(int v, int val) {
V[v].propagate = true;
V[v].propWith = val;
if (val == 0) { // Clearing rooms (Freeing)
V[v].pref = V[v].suff = V[v].best = V[v].len;
} else { // Occupying rooms (Filling)
V[v].pref = V[v].suff = V[v].best = 0;
}
}
void propagate(int v) {
if(V[v].propagate == false)
return;
apply(v * 2, V[v].propWith);
apply(v * 2 +1, V[v].propWith);
V[v].propagate = false;
}
void op(int v, int l, int r, int updateL, int updateR, int propType) {
if(l > updateR || r < updateL)
return;
if(updateL <= l && r <= updateR) {
apply(v, propType);
return;
}
propagate(v);
int mij = (l + r) / 2;
int left = v * 2, right = v * 2 + 1;
op(left, l, mij, updateL, updateR, propType);
op(right, mij+1, r, updateL, updateR, propType);
V[v].pref = V[left].pref;
if (V[left].pref == V[left].len) {
V[v].pref = V[left].len + V[right].pref;
}
V[v].suff = V[right].suff;
if (V[right].suff == V[right].len) {
V[v].suff = V[right].len + V[left].suff;
}
V[v].best = max({
V[left].best,
V[right].best,
V[left].suff + V[right].pref
});
}
Segtree query(int v, int l, int r, int updateL, int updateR) {
if(l > updateR || r < updateL) {
Segtree empty;
empty.len = 0;
empty.pref = empty.suff = empty.best = 0;
empty.propagate = false;
return empty;
}
if(updateL <= l && r <= updateR)
return V[v];
propagate(v);
int mij = (l + r) / 2;
int left = v * 2, right = v * 2 + 1;
Segtree A = query(left, l, mij, updateL, updateR);
Segtree B = query(right, mij+1, r, updateL, updateR);
Segtree res;
res.len = A.len + B.len;
res.pref = A.pref;
res.suff = B.suff;
if(A.pref == A.len)
res.pref = A.len + B.pref;
if(B.suff == B.len)
res.suff = B.len + A.suff;
res.best = max(
max(A.best, B.best),
A.suff + B.pref);
return res;
}
int main()
{
int n, P, cer, a, b;
fin>>n>>P;
build(1, 1, n);
for(int p = 1; p <= P; p++) {
fin>>cer;
if(cer!=3)
fin>>a>>b;
if(cer==1) {
op(1, 1, n, a, a + b - 1, 1); // we fill
}
else if(cer==2) {
op(1, 1, n, a, a + b - 1, 0); // we empty
}
else {
fout<<query(1, 1, n, 1, n).best<<'\n';
}
}
return 0;
}