#include <fstream>
#include <vector>
std::ifstream fin("hotel.in");
std::ofstream fout("hotel.out");
using namespace std;
struct node
{
int sum,pref,suff,best; //
};
class ArbINT
{
vector<node> A;
vector<int> Lazy;
int size_of_array;
public:
ArbINT(int sz)
{
size_of_array = sz;
A.resize(4*size_of_array+5,{0,0,0,0});
Lazy.resize(4*size_of_array+5,0);
}
void Build()
{
BuildUtil(1,1,size_of_array);
}
void Update(int st,int dr,int val)
{
UpdateUtil(1,1,size_of_array,st,dr,val);
}
int Querry()
{
return A[1].best;
}
private:
void BuildUtil(int nod,int st,int dr)
{
if(st == dr)
{
A[nod] = {1,1,1,1};
}
else
{
int mid = (st+dr)/2;
BuildUtil(2*nod,st,mid);
BuildUtil(2*nod+1,mid+1,dr);
A[nod].sum = A[2*nod].sum+A[2*nod+1].sum;
A[nod].pref = A[2*nod].pref;
if(A[2*nod].sum == mid - st + 1)
A[nod].pref = max(A[nod].pref,A[2*nod].sum + A[2*nod+1].pref);
A[nod].suff = A[2*nod+1].suff;
if(A[2*nod + 1].sum == dr - mid)
A[nod].suff = max(A[nod].suff,A[2*nod].suff + A[2*nod+1].sum);
//A[nod].best = max({A[2*nod].best,A[2*nod+1].best,A[2*nod].suff+A[2*nod+1].pref,A[nod].suff,A[nod].pref});
A[nod].best = A[2*nod].best;
A[nod].best = max(A[nod].best,A[2*nod+1].best);
A[nod].best = max(A[nod].best,A[2*nod].suff+A[2*nod+1].pref);
A[nod].best = max(A[nod].best,A[nod].suff);
A[nod].best = max(A[nod].best,A[nod].pref);
}
}
void UpdateUtil(int nod,int st,int dr,int a,int b,int val)
{
if(a <= st && dr <= b)
{
val += Lazy[nod];
Lazy[nod] = 0;
if(st != dr)
{
Lazy[2*nod] += val;
Lazy[2*nod+1] += val;
}
if(val == -1)
{
A[nod] = {0,0,0,0};
}
if(val == 1)
{
A[nod] = {dr-st+1,dr-st+1,dr-st+1,dr-st+1};
}
// fout << "Coord nod inclus\n";
// fout << st << ' ' << dr << '\n';
// fout << A[nod].sum << ' ' << A[nod].pref << ' ' << A[nod].suff << ' ' << A[nod].best << '\n';
}
else
{
int mid = (st+dr)/2;
Lazy[2*nod] += Lazy[nod];
Lazy[2*nod+1] += Lazy[nod];
Lazy[nod] = 0;
if(a <= mid)
UpdateUtil(2*nod,st,mid,a,b,val);
if(b > mid)
UpdateUtil(2*nod+1,mid+1,dr,a,b,val);
node left = A[2*nod];
node right = A[2*nod+1];
if(Lazy[2*nod] == -1)
left = {0,0,0,0};
if(Lazy[2*nod] == 1)
left = {mid - st + 1,mid - st + 1,mid - st + 1,mid - st + 1};
if(Lazy[2*nod+1] == -1)
right = {0,0,0,0};
if(Lazy[2*nod+1] == 1)
right = {dr - mid,dr - mid,dr - mid,dr - mid};
A[nod].sum = left.sum+ right.sum;
A[nod].pref = left.pref;
if( left.sum == mid - st + 1)
A[nod].pref = max(A[nod].pref,left.sum + right.pref);
A[nod].suff = right.suff;
if( right.sum == dr - mid)
A[nod].suff = max(A[nod].suff, left.suff + A[2*nod+1].sum);
//A[nod].best = max({A[2*nod].best,A[2*nod+1].best,A[2*nod].suff+A[2*nod+1].pref,A[nod].suff,A[nod].pref});
A[nod].best = left.best;
A[nod].best = max(A[nod].best, right.best);
A[nod].best = max(A[nod].best, left.suff+ right.pref);
A[nod].best = max(A[nod].best,A[nod].suff);
A[nod].best = max(A[nod].best,A[nod].pref);
// fout << "Coords:\n";
// fout << st << ' ' << mid << ' ' << mid + 1 << ' ' << dr << '\n';
// fout << left.suff << ' ' << right.pref << '\n';
}
}
// node QuerryUtil(int nod,int st,int dr,int a,int b)
// {
// fout << st << ' ' << dr << '\n';
// fout << a << ' ' << b << '\n';
// if(a <= st && dr <= b)
// {
// if(Lazy[nod] == -1)
// {
// A[nod] = {0,0,0,0};
// }
// if(Lazy[nod] == 1)
// {
// A[nod] = {dr-st+1,dr-st+1,dr-st+1,dr-st+1};
// }
// if(st != dr)
// {
// Lazy[2*nod] += Lazy[nod];
// Lazy[2*nod+1] += Lazy[nod];
// }
// Lazy[nod] = 0;
//
// return A[nod];
// }
// else
// {
// int mid = (st+dr)/2;
// Lazy[2*nod] = Lazy[nod];
// Lazy[2*nod+1] = Lazy[nod];
// Lazy[nod] = 0;
// if(a <= mid)
// QuerryUtil(2*nod,st,mid,a,b);
// if(b > mid)
// QuerryUtil(2*nod+1,mid+1,dr,a,b);
// A[nod].sum = A[2*nod].sum+A[2*nod+1].sum;
// A[nod].pref = A[2*nod].pref;
// if(A[2*nod].sum == mid - st + 1)
// A[nod].pref = max(A[nod].pref,A[2*nod].sum + A[2*nod+1].pref);
// A[nod].suff = A[2*nod+1].suff;
// if(A[2*nod + 1].sum == dr - mid)
// A[nod].suff = max(A[nod].suff,A[2*nod].suff + A[2*nod+1].sum);
// //A[nod].best = max({A[2*nod].best,A[2*nod+1].best,A[2*nod].suff+A[2*nod+1].pref,A[nod].suff,A[nod].pref});
// A[nod].best = A[2*nod].best;
// A[nod].best = max(A[nod].best,A[2*nod+1].best);
// A[nod].best = max(A[nod].best,A[2*nod].suff+A[2*nod+1].pref);
// A[nod].best = max(A[nod].best,A[nod].suff);
// A[nod].best = max(A[nod].best,A[nod].pref);
// return A[nod];
// }
// }
};
int main()
{
int N,Q;
fin >> N >> Q;
ArbINT AINT(N);
AINT.Build();
int cer,st,x,ind = 0;
while(Q--)
{
fin >> cer;
if(cer == 1)
{
fin >> st >> x;
//fout << "ID " << ++ind << '\n';
AINT.Update(st,st+x-1,-1);
}
else if(cer == 2)
{
fin >> st >> x;
//fout << "ID " << ++ind << '\n';
AINT.Update(st,st+x-1,1);
}
else
{
fout << AINT.Querry() << '\n';
}
}
}