#include <iostream>
#include <fstream>
#include <stack>
#include <queue>
#include <vector>
#include <map>
#include <cctype>
#include <unordered_map>
#include <cmath>
#include <bitset>
#include <set>
#include <string>
#include <cstring>
#include <algorithm>
#include <deque>
using namespace std;
ifstream in("hotel.in");
ofstream out("hotel.out");
int a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,S,t,x,y,z,ok,nr,C,xc,yc,Min,w,poz,ans,cost,Max;
struct Tree{
int lazy;
int max0,upst,updr;
bool st,dr;
};
Tree T[500005];
Tree Combine(Tree leftT,Tree rightT,int left,int right){
Tree NewT;
int k=-1;
int mid=(left+right)/2;
k=max(leftT.max0,rightT.max0);
if(leftT.dr==true && rightT.st==true && rightT.upst-leftT.updr+1>=k){
k=rightT.upst-leftT.updr+1;
NewT.max0=k;
NewT.st=leftT.st;
NewT.dr=rightT.dr;
if(leftT.upst==mid) {NewT.upst=rightT.upst;}
else {NewT.upst=leftT.upst;}
if(rightT.updr==mid+1) {NewT.updr=leftT.updr;}
else {NewT.updr=rightT.updr;}
}
else{
NewT.max0=k;
NewT.st=leftT.st;
NewT.dr=rightT.dr;
if(leftT.upst==mid) {NewT.upst=rightT.upst;}
else {NewT.upst=leftT.upst;}
if(rightT.updr==mid+1) {NewT.updr=leftT.updr;}
else {NewT.updr=rightT.updr;}
}
return NewT;
}
void Up(int node,int left,int right){
if(T[node].lazy==1){
T[node].lazy=0;
T[node].st=false;
T[node].dr=false;
T[node].upst=left;
T[node].updr=right;
T[node].max0=0;
if(left!=right){
T[2*node].lazy=1;
T[2*node+1].lazy=1;
}
}
if(T[node].lazy==2){
T[node].lazy=0;
T[node].st=true;
T[node].dr=true;
T[node].upst=right;
T[node].updr=left;
T[node].max0=right-left+1;
if(left!=right){
T[2*node].lazy=2;
T[2*node+1].lazy=2;
}
}
}
void Build(int node,int left,int right){
if(left==right){
T[node].st=true;
T[node].dr=true;
T[node].upst=left;
T[node].updr=left;
T[node].lazy=0;
T[node].max0=1;
}
else{
int mid=(left+right)/2;
Build(2*node,left,mid);
Build(2*node+1,mid+1,right);
T[node]=Combine(T[2*node],T[2*node+1],left,right);
}
}
void Sosire(int node,int left,int right,int left_q,int right_q){
Up(node,left,right);
if(left_q<=left && right<=right_q){
T[node].lazy=1;
Up(node,left,right);
}
else{
int mid=(left+right)/2;
if(left_q<=mid) {
Sosire(2*node,left,mid,left_q,right_q);
}
if(right_q>=mid+1) {
Sosire(2*node+1,mid+1,right,left_q,right_q);
}
Up(2*node,left,mid);
Up(2*node+1,mid+1,right);
T[node]=Combine(T[2*node],T[2*node+1],left,right);
}
}
void Plecare(int node,int left,int right,int left_q,int right_q){
Up(node,left,right);
if(left_q<=left && right<=right_q){
T[node].lazy=2;
Up(node,left,right);
}
else{
int mid=(left+right)/2;
if(left_q<=mid) {
Plecare(2*node,left,mid,left_q,right_q);
}
if(right_q>=mid+1) {
Plecare(2*node+1,mid+1,right,left_q,right_q);
}
Up(2*node,left,mid);
Up(2*node+1,mid+1,right);
T[node]=Combine(T[2*node],T[2*node+1],left,right);
}
}
int main()
{
in>>n>>p;
Build(1,1,n);
for(e=1;e<=p;e++){
in>>t;
if(t==1){
in>>x>>y;
z=min(n,x+y-1);
Sosire(1,1,n,x,z);
}
if(t==2){
in>>x>>y;
z=min(n,x+y-1);
Plecare(1,1,n,x,z);
}
if(t==3){
Up(1,1,n);
out<<T[1].max0<<'\n';
}
}
return 0;
}