#include <fstream>
using namespace std;
ifstream fin("hotel.in");
ofstream fout("hotel.out");
struct {
int lazy;
int liberMax, liberSufix, liberPrefix;
}arb[400005];
int tip, a, b;
int n, q, op;
void propagate(int nod,int st, int dr){
if(arb[nod].lazy == 1 && st != dr) {
arb[nod * 2].lazy = 1;
arb[nod * 2 + 1].lazy = 1;
if(arb[nod].liberMax == 0) { // nodul curent este ocupat, trebuie sa ocupam si fiii
arb[nod * 2].liberMax = arb[nod * 2].liberSufix = arb[nod * 2].liberPrefix = 0;
arb[nod * 2 + 1].liberMax = arb[nod * 2 + 1].liberSufix = arb[nod * 2 + 1].liberPrefix = 0;
} else {
int mij = (st + dr) / 2;
arb[nod * 2].liberMax = arb[nod * 2].liberSufix = arb[nod * 2].liberPrefix = mij - st + 1;
arb[nod * 2 + 1].liberMax = arb[nod * 2 + 1].liberSufix = arb[nod * 2 + 1].liberPrefix = dr - mij;
}
arb[nod].lazy = 0;
}
}
void build(int nod = 1, int st = 1, int dr = n) {
if(st == dr) {
arb[nod].liberMax=1;
arb[nod].liberSufix=1;
arb[nod].liberPrefix=1;
return;
}
int mij = (st + dr) / 2;
build(2 * nod, st, mij);
build(2 * nod + 1, mij + 1, dr);
arb[nod].liberMax = dr-st+1;
arb[nod].liberSufix = dr-st+1;
arb[nod].liberPrefix = dr-st+1;
}
void update1(int a, int b, int nod=1, int st=1, int dr=n){
propagate(nod,st,dr);
if(dr < a || st > b) return;
if(st >= a && dr <= b) {
/// se afla in interval, totul devine e ocupat
/// deci toate devin 0
arb[nod].liberMax=0;
arb[nod].liberSufix=0;
arb[nod].liberPrefix=0;
arb[nod].lazy = 1;
return;
}
int mij=(st+dr)/2;
if(a<=mij){
update1(a,b,2*nod,st,mij);
}
if(mij<b){
update1(a,b,2*nod+1,mij+1,dr);
}
propagate(nod * 2, st, mij);
propagate(nod * 2 + 1, mij + 1, dr);
arb[nod].liberMax = max(max(arb[nod * 2].liberMax, arb[nod * 2 + 1].liberMax),
arb[nod * 2].liberSufix + arb[nod * 2 + 1].liberPrefix);
arb[nod].liberSufix = (arb[nod * 2 + 1].liberSufix == (dr - mij) ? arb[nod * 2].liberSufix + (dr - mij) : arb[nod * 2 + 1].liberSufix);
arb[nod].liberPrefix = (arb[nod * 2].liberPrefix == (mij - st + 1) ? arb[nod * 2 + 1].liberPrefix + (mij - st + 1) : arb[nod * 2].liberPrefix);
}
void update2(int a, int b, int nod=1, int st=1, int dr=n){
propagate(nod,st,dr);
if(dr < a || st > b) return;
if(st >= a && dr <= b) {
/// se afla in interval, totul devine e ocupat
/// deci toate devin maxime
arb[nod].liberMax=dr-st+1;
arb[nod].liberSufix=dr-st+1;
arb[nod].liberPrefix=dr-st+1;
arb[nod].lazy = 1;
return;
}
int mij=(st+dr)/2;
if(a<=mij){
update2(a,b,2*nod,st,mij);
}
if(mij<b){
update2(a,b,2*nod+1,mij+1,dr);
}
propagate(nod * 2, st, mij);
propagate(nod * 2 + 1, mij + 1, dr);
arb[nod].liberMax = max(max(arb[nod * 2].liberMax, arb[nod * 2 + 1].liberMax),
arb[nod * 2].liberSufix + arb[nod * 2 + 1].liberPrefix);
arb[nod].liberSufix = (arb[nod * 2 + 1].liberSufix == (dr - mij) ? arb[nod * 2].liberSufix + (dr - mij) : arb[nod * 2 + 1].liberSufix);
arb[nod].liberPrefix = (arb[nod * 2].liberPrefix == (mij - st + 1) ? arb[nod * 2 + 1].liberPrefix + (mij - st + 1) : arb[nod * 2].liberPrefix);
}
int main()
{
fin>>n>>q;
build();
for(int i=1;i<=q;i++){
fin>>op;
if(op==1){
fin>>a>>b;
update1(a,a+b-1);
}
else if(op==2){
fin>>a>>b;
update2(a,a+b-1);
}
else{
fout<<arb[1].liberMax<<'\n';
}
}
return 0;
}