#include <iostream>
#include <fstream>
#include <vector>
#include <algorithm>
#include <cmath>
using namespace std;
ifstream fin("hotel.in");
ofstream fout("hotel.out");
struct node {
int liber;//daca tot intervalul st,dr e liber
int pref;//nr maxim de locuri libere din prefix aka (st,....)
int sufix;//nr maxim de locuri libere din prefix de la (....dr)
int total;//nr maxim libere per total
//liber=0=> toate sunt libere
//liber=1=> toate sunt ocupate
//liber=-1=> nu e determinat
node() :liber(-1), pref(0), sufix(0), total(0) {};
node(int val):liber(0), pref(val), sufix(val), total(val) {};
};
struct AINT {
vector<node>aint;
void combin(node& crt, node& st, node& dr) {
crt.sufix = dr.sufix;
if (dr.liber==0) {
crt.sufix += st.sufix;
}
crt.pref = st.pref;
if (st.liber==0) {
crt.pref +=dr.pref;
}
if (st.liber == 1 && dr.liber == 1) {
crt.liber = 1;
}
else if (st.liber == 0 && dr.liber == 0) {
crt.liber = 0;
}
else {
crt.liber = -1;
}
crt.total = max(dr.total, st.total);
crt.total = max(crt.total, st.sufix+dr.pref);
}
void resizeAint(int& n) {
int logCrt = log2(n);
if ((1 << logCrt) == n) {
logCrt++;
}
aint.resize(1 << (1 + logCrt)+1);
}
void updateInterval(int pozTree, int st, int dr,int stUpdate,int drUpdate,bool leave) {
int mij = (st + dr) / 2;
int leftChild = 2 * pozTree;
int rightChild = 2 * pozTree + 1;
if (st >= stUpdate && dr <= drUpdate) {
if (leave) {
aint[pozTree].liber = 0;
aint[pozTree].pref = (dr - st + 1);
aint[pozTree].sufix = (dr - st + 1);
aint[pozTree].total = (dr - st + 1);
}
else {
aint[pozTree].liber = 1;
aint[pozTree].pref = 0;
aint[pozTree].sufix = 0;
aint[pozTree].total = 0;
}
return;
}
if (aint[pozTree].liber == 1) {//adaugam starile anterioare
aint[leftChild].liber = 1;
aint[leftChild].pref = 0;
aint[leftChild].sufix = 0;
aint[leftChild].total = 0;
aint[rightChild].liber = 1;
aint[rightChild].pref = 0;
aint[rightChild].sufix = 0;
aint[rightChild].total = 0;
}
if (aint[pozTree].liber == 0) {//adaugam starile anterioare
aint[leftChild].liber = 0;
aint[leftChild].pref = mij - st + 1;
aint[leftChild].sufix = mij - st + 1;
aint[leftChild].total = mij - st + 1;
aint[rightChild].liber = 0;
aint[rightChild].pref = (dr - mij);
aint[rightChild].sufix = (dr - mij);
aint[rightChild].total = (dr - mij);
}
if (stUpdate <= mij) {
updateInterval(leftChild, st, mij, stUpdate, drUpdate, leave);
}
if (drUpdate > mij) {
updateInterval(rightChild,mij+1,dr, stUpdate, drUpdate, leave);
}
combin(aint[pozTree], aint[leftChild], aint[rightChild]);
}
void buildAint(int pozTree, int st, int dr) {
if (st == dr) {
aint[pozTree].liber = 0;
aint[pozTree].sufix = 1;
aint[pozTree].pref = 1;
aint[pozTree].total = 1;
return;
}
int mij = (st + dr) / 2;
int leftChild = 2 * pozTree;
int rightChild = 2 * pozTree + 1;
buildAint(leftChild, st, mij);
buildAint(rightChild, mij+1, dr);
combin(aint[pozTree], aint[leftChild], aint[rightChild]);
}
};
int main()
{
int n,q;
fin >> n>>q;
AINT crt;
crt.resizeAint(n);
crt.buildAint(1, 0, n - 1);
int op, st, cnt;
while (q)
{
fin >> op;
switch (op)
{
case 1:
fin >> st >> cnt;
crt.updateInterval(1, 0, n - 1, st-1, st-2+cnt, 0);
break;
case 2:
fin >> st >> cnt;
crt.updateInterval(1, 0, n - 1, st - 1, st - 2 + cnt, 1);
break;
default:
fout << crt.aint[1].total << "\n";
break;
}
--q;
}
return 0;
}
//=^..^=