#include <bits/stdc++.h>
using namespace std;
const int NMAX = 100003;
int n,q;
struct elem{
int state,pre,suf,lazy;
};
// 1 liber
// 0 ocupat
// stte rasp
class segtree{
private:
elem t[3*NMAX];
public:
void build(int nod,int st,int dr){
if(st==dr){
t[nod].state=1;
t[nod].pre=1;
t[nod].suf=1;
t[nod].lazy=0;
return ;
}
int mid=(st+dr)>>1;
build(2*nod,st,mid);
build(2*nod+1,mid+1,dr);
t[nod].state=dr-st+1;
t[nod].pre=dr-st+1;
t[nod].suf=dr-st+1;
t[nod].lazy=0;
}
// val == 0 nu se intampla nimic
// val == 1 umplere
// val == 2 golire
void update(int nod,int st,int dr,int x,int y,int val){
if(t[nod].lazy){
int aux=(t[nod].lazy ? 0 : dr-st+1 );
if(st<dr){
t[2*nod].lazy=t[nod].lazy;
t[2*nod+1].lazy=t[nod].lazy;
}
t[nod].lazy=0;
t[nod].state=aux;
t[nod].pre=aux;
t[nod].suf=aux;
}
if(dr<x || st>y)return ;// [st,dr] disjunct cu [x,y]
if(x<=st && dr<=y){
int aux=(val==1 ? 0 : dr-st+1);
t[nod].state=aux;
t[nod].pre=aux;
t[nod].suf=aux;
if(st<dr){
t[2*nod].lazy=val;
t[2*nod+1].lazy=val;
}
return ;
}
int mid=(st+dr)>>1;
update(2*nod,st,mid,x,y,val);
update(2*nod+1,mid+1,dr,x,y,val);
t[nod].state=max(t[2*nod].state,max(t[2*nod+1].state,t[2*nod].suf+t[2*nod+1].pre ) );
t[nod].pre=t[2*nod].pre;
if(t[2*nod].state==mid-st+1)t[nod].pre=t[2*nod].state+t[2*nod+1].pre;
t[nod].suf=t[2*nod+1].suf;
if(t[2*nod+1].state==dr-mid)t[nod].suf=t[2*nod+1].state+t[2*nod].suf;
}
int query(){
return t[1].state;
}
}sg;
int main()
{
freopen("hotel.in","r",stdin);
freopen("hotel.out","w",stdout);
scanf("%d %d",&n,&q);
sg.build(1,1,n);
while(q--){
int type;
scanf("%d",&type);
if(type==1){
int x,y;
scanf("%d %d",&x,&y);
sg.update(1,1,n,x,x+y-1,1);
}else if(type==2){
int x,y;
scanf("%d %d",&x,&y);
sg.update(1,1,n,x,x+y-1,2);
}else{
printf("%d\n",sg.query());
}
}
return 0;
}