#include <iostream>
#include <fstream>
#include <vector>
using namespace std;
class SegmentTree {
public:
struct Node {
int length, null_prefix, null_suffix, null_sequence;
Node operator+(Node const &that) const {
return {
length + that.length,
(null_sequence == length)? length + that.null_prefix : null_prefix,
(that.null_sequence == that.length)? that.length + null_suffix : that.null_suffix,
max(max(null_sequence, that.null_sequence), null_suffix + that.null_prefix)
};
}
};
private:
vector<Node> v;
int N;
void propagate(int node, int nl, int nr) {
int nm = (nl + nr) / 2;
if (v[node].null_sequence == 0) {
v[2*node].null_prefix = v[2*node].null_suffix = v[2*node].null_sequence = 0;
v[2*node+1].null_prefix = v[2*node+1].null_suffix = v[2*node+1].null_sequence = 0;
}
if (v[node].null_sequence == v[node].length) {
v[2*node].null_prefix = v[2*node].null_suffix = v[2*node].null_sequence = nm - nl;
v[2*node+1].null_prefix = v[2*node+1].null_suffix = v[2*node+1].null_sequence = nr - nm;
}
}
void _fill(int node, int nl, int nr, int sl, int sr) {
v[node].length = nr - nl;
if (sr <= nl || nr <= sl || nr <= nl) {
return;
}
if (sl <= nl && nr <= sr) {
v[node].null_prefix = 0;
v[node].null_suffix = 0;
v[node].null_sequence = 0;
return;
}
int nm = (nl + nr) / 2;
propagate(node, nl, nr);
_fill(2*node, nl, nm, sl, sr);
_fill(2*node+1, nm, nr, sl, sr);
v[node] = v[2*node] + v[2*node+1];
return;
}
void _free(int node, int nl, int nr, int sl, int sr) {
v[node].length = nr - nl;
if (sr <= nl || nr <= sl || nr <= nl) {
return;
}
if (sl <= nl && nr <= sr) {
v[node].null_prefix = v[node].length;
v[node].null_suffix = v[node].length;
v[node].null_sequence = v[node].length;
return;
}
int nm = (nl + nr) / 2;
propagate(node, nl, nr);
_free(2*node, nl, nm, sl, sr);
_free(2*node+1, nm, nr, sl, sr);
v[node] = v[2*node] + v[2*node+1];
return;
}
Node _query(int node, int nl, int nr, int sl, int sr) {
if (sr <= nl || nr <= sl || nr <= nl) {
return {0, 0, 0, 0};
}
if (sl <= nl && nr <= sr) {
return v[node];
}
int nm = (nl + nr) / 2;
propagate(node, nl, nr);
return _query(2*node, nl, nm, sl, sr) + _query(2*node+1, nm, nr, sl, sr);
}
void build(int node, int nl, int nr) {
v[node].length = nr - nl;
v[node].null_prefix = nr - nl;
v[node].null_suffix = nr - nl;
v[node].null_sequence = nr - nl;
if (nr - nl == 1) {
return;
}
int nm = (nl + nr) / 2;
build(2*node, nl, nm);
build(2*node+1, nm, nr);
}
public:
SegmentTree(int N) : N(N), v(4*N) {
build(1, 0, N);
}
void fill(int l, int r) {
_fill(1, 0, N, l, r);
}
void free(int l, int r) {
_free(1, 0, N, l, r);
}
int query(int l, int r) {
return _query(1, 0, N, l, r).null_sequence;
}
int all() {
return v[1].null_sequence;
}
};
int main() {
ifstream fin("hotel.in");
ofstream fout("hotel.out");
int N, P;
fin >> N >> P;
SegmentTree st(N);
for (int p = 0; p < P; ++p) {
int opcode;
fin >> opcode;
if (opcode <= 2) {
int i, M;
fin >> i >> M;
--i;
if (opcode == 1) {
st.fill(i, i+M);
} else if (opcode == 2) {
st.free(i, i+M);
}
} else if (opcode == 3) {
fout << st.all() << '\n';
}
}
return 0;
}