#include <cstdio>
#include <cstring>
#include <algorithm>
#include <vector>
#include <string>
#include <iostream>
#include <list>
#include <queue>
//#include <conio.h>
#define pb push_back
#define mp make_pair
#define MOD 1000000007
#define newl printf("\n")
#define NMAX 100005
#define nst (nod<<1)
#define ndr (nst+1)
using namespace std;
int n,m,lazy[NMAX<<2];
struct node
{
int bestLeft,bestRight,best;
node(){}
};
node tree[NMAX<<2];
node make_node(int x)
{
node t;
t.bestLeft=t.bestRight=t.best=x;
return t;
}
node combine(node left,node right,int st,int dr)
{
node t;
int mid=(st+dr)>>1;
t.bestLeft=left.bestLeft;
if (t.bestLeft==mid-st+1) t.bestLeft+=right.bestLeft;
t.bestRight=right.bestRight;
if (t.bestRight==dr-mid) t.bestRight+=left.bestRight;
t.best=max(max(left.best,right.best),left.bestRight+right.bestLeft);
return t;
}
void build(int nod,int st,int dr)
{
if (st==dr)
{
tree[nod]=make_node(dr-st+1);
return;
}
int mid=(st+dr)>>1;
build(nst,st,mid);
build(ndr,mid+1,dr);
tree[nod]=combine(tree[nst],tree[ndr],st,dr);
}
void update(int nod,int st,int dr,int a,int b,int val)
{
if (lazy[nod])
{
if (lazy[nod]==1) tree[nod]=make_node(0);
else tree[nod]=make_node(dr-st+1);
if (st!=dr)
{
lazy[nst]=lazy[nod];
lazy[ndr]=lazy[nod];
}
lazy[nod]=0;
}
if (st>b || dr<a) return;
if (a<=st && dr<=b)
{
if (val==1) tree[nod]=make_node(0);
else tree[nod]=make_node(dr-st+1);
if (st!=dr)
{
lazy[nst]=val;
lazy[ndr]=val;
}
return;
}
int mid=(st+dr)>>1;
update(nst,st,mid,a,b,val);
update(ndr,mid+1,dr,a,b,val);
tree[nod]=combine(tree[nst],tree[ndr],st,dr);
}
int main()
{
freopen("hotel.in","r",stdin);
freopen("hotel.out","w",stdout);
scanf("%d %d",&n,&m);
build(1,1,n);
int type,a,b;
while (m--)
{
scanf("%d",&type);
if (type==1)
{
scanf("%d %d",&a,&b);
b=a+b-1;
update(1,1,n,a,b,1);
}
else if (type==2)
{
scanf("%d %d",&a,&b);
b=a+b-1;
update(1,1,n,a,b,2);
}
else printf("%d\n",tree[1].best);
}
return 0;
}