#include <bits/stdc++.h>
#include <random>
#include <chrono>
using namespace std;
mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());
const char nl = '\n';
const char sp = ' ';
const int inf = 0x3f3f3f3f;
const long long INF = 1000000000000000000;
const int mod = 1e9 + 7;
const char out[2][4]{ "NO", "YES" };
#define all(A) A.begin(), A.end()
using ll = long long;
ifstream fin("hotel.in");
ofstream fout("hotel.out");
#define variableName(var) #var
#define __debug(var) cout << #var << " = " << var << '\n'
inline int rint(int a, int b) { return uniform_int_distribution<int>(a, b)(rng); }
struct TreeNode {
int prefix;
int suffix;
int length;
int secvmax;
TreeNode() {
prefix = suffix = length = secvmax = 0;
}
TreeNode(bool empty) {
prefix = suffix = secvmax = empty;
length = 1;
}
void set() {
prefix = suffix = secvmax = length;
}
void reset() {
prefix = suffix = secvmax = 0;
}
friend TreeNode merge(const TreeNode& lhs, const TreeNode& rhs) {
TreeNode res;
res.prefix = rhs.prefix == rhs.length ? rhs.length + lhs.prefix : rhs.prefix;
res.suffix = lhs.suffix == lhs.length ? rhs.suffix + lhs.length : lhs.suffix;
res.length = rhs.length + lhs.length;
res.secvmax = max({ rhs.secvmax, lhs.secvmax, rhs.suffix + lhs.prefix });
return res;
}
};
struct SegmentTree {
private:
vector<TreeNode> t;
vector<int> lazy;
int size;
inline void apply_lazy(int node, int l, int r) {
if (lazy[node] != -1) {
if (lazy[node] == 1) {
t[node].set();
}
else {
t[node].reset();
}
if (l != r) {
lazy[node << 1] = lazy[node];
lazy[node << 1 | 1] = lazy[node];
}
lazy[node] = -1;
}
}
void build(int node, int l, int r) {
lazy[node] = -1;
if (l == r) {
t[node] = TreeNode(true);
return;
}
int mid = (l + r) / 2;
build(node << 1, l, mid);
build(node << 1 | 1, mid + 1, r);
t[node] = merge(t[node << 1], t[node << 1 | 1]);
}
void set(int node, int l, int r, int ql, int qr) {
apply_lazy(node, l, r);
if (l > qr || r < ql) {
return;
}
if (ql <= l && r <= qr) {
lazy[node] = 1;
apply_lazy(node, l, r);
return;
}
int mid = (l + r) / 2;
set(node << 1, l, mid, ql, qr);
set(node << 1 | 1, mid + 1, r, ql, qr);
t[node] = merge(t[node << 1], t[node << 1 | 1]);
}
void reset(int node, int l, int r, int ql, int qr) {
apply_lazy(node, l, r);
if (l > qr || r < ql) {
return;
}
if (ql <= l && r <= qr) {
lazy[node] = 0;
apply_lazy(node, l, r);
return;
}
int mid = (l + r) / 2;
reset(node << 1, l, mid, ql, qr);
reset(node << 1 | 1, mid + 1, r, ql, qr);
t[node] = merge(t[node << 1], t[node << 1 | 1]);
}
public:
void build(int size) {
this->size = size;
t.resize(4 * size + 5);
lazy.resize(4 * size + 5);
build(1, 1, size);
}
void set(int l, int r) {
set(1, 1, size, l, r);
}
void reset(int l, int r) {
reset(1, 1, size, l, r);
}
int query() {
return t[1].secvmax;
}
} tree;
int n, q;
int main() {
ios::sync_with_stdio(0);
cin.tie(0);
fin >> n >> q;
tree.build(n);
while (q--) {
int t, i, m;
fin >> t;
if (t == 1) {
fin >> i >> m;
tree.reset(i, i + m - 1);
}
else if (t == 2) {
fin >> i >> m;
tree.set(i, i + m - 1);
}
else {
fout << tree.query() << nl;
}
}
}