#include <fstream>
#include <algorithm>
using namespace std;
ifstream fin("hotel.in");
ofstream fout("hotel.out");
#define DIM 100000
#define BUSY 1
#define FREE 2
int n, m;
struct nanu {
int maxim;
int left_max; //suma maxima din stanga;
int right_max; //suma maxima din dreapta;
int lazy;
}tree[DIM * 4 + 1];
static inline void Lazy_update(int st, int dr, int nod) {
if(tree[nod].lazy == BUSY) { //daca e ocupat il eliberez;
tree[nod] = {0, 0, 0, BUSY};
if(st != dr) { //sa nu fie frunza;
tree[nod * 2].lazy = BUSY;
tree[nod * 2 + 1].lazy = BUSY;
}
}else if(tree[nod].lazy == FREE) {
tree[nod] = {dr - st + 1, dr - st + 1, dr - st + 1, FREE}; //toate camerele devin 0 si lungimea secventei este dr - st + 1;
if(st != dr) {
tree[nod * 2].lazy = FREE;
tree[nod * 2 + 1].lazy = FREE;
}
}
tree[nod].lazy = 0;
}
static inline void Merge(int st, int dr, int nod) {
int mid = (st + dr) / 2;
tree[nod].left_max = (tree[nod * 2].left_max == mid - st + 1) ? (mid - st + 1) + tree[nod * 2 + 1].left_max : tree[nod * 2].left_max;
tree[nod].right_max = (tree[nod * 2 + 1].right_max == dr - mid) ? (dr - mid) + tree[nod * 2].right_max : tree[nod * 2 + 1].right_max;
tree[nod].maxim = max(tree[nod * 2].right_max + tree[nod * 2 + 1].left_max, max(tree[nod * 2].left_max, tree[nod * 2 + 1].right_max));
}
static inline void Update(int st, int dr, int nod, int leftq, int rightq, int type) {
if(leftq <= st & dr <= rightq)
tree[nod].lazy = type;
else {
int mid = (st + dr) / 2;
Lazy_update(st, dr, nod);
if(leftq <= mid)
Update(st, mid, nod * 2, leftq, rightq, type);
if(mid < rightq)
Update(mid + 1, dr, nod * 2 + 1, leftq, rightq, type);
Lazy_update(st, mid, nod * 2);
Lazy_update(mid + 1, dr, nod * 2 + 1);
Merge(st, dr, nod); //solutia oprima;
}
}
int main() {
fin >> n >> m;
tree[1].lazy = 2;
for(int i = 1; i <= m; i++) {
int tip, x, y;
fin >> tip;
if(tip <= 2) {
fin >> x >> y;
Update(1, n, 1, x, x + y - 1, tip);
}else {
Lazy_update(1, n, 1); //sa nu am vreun update de facut;
fout << tree[1].maxim << '\n';
}
}
return 0;
}