#include <vector>
#include <fstream>
#include <climits>
#include <algorithm>
typedef long long ll;
std::ifstream cin("hotel.in");
std::ofstream cout("hotel.out");
const int NMAX = 100005;
struct nod {
int st,dr,rez;
};
nod Tree[NMAX*4];
int lazy[NMAX*4];
void prop(int nod,int st,int dr) {
if (lazy[nod] == -1) return;
if (lazy[nod]) {
Tree[nod] = {.st = 0, .dr = 0, .rez = 0};
if (st != dr) {
lazy[nod*2] = lazy[nod*2+1] = 1;
}
}
else {
Tree[nod] = {.st = dr-st+1, .dr = dr-st+1, .rez = dr-st+1};
if (st != dr) {
lazy[nod*2] = lazy[nod*2+1] = 0;
}
}
lazy[nod] = -1;
}
void Uppdate(int nod,int st,int dr, int l, int r,int val) {
prop(nod,st,dr);
if (r < st || dr < l) {
return;
}
if (l <= st && dr <= r) {
lazy[nod] = val;
prop(nod,st,dr);
return;
}
int mid = (st + dr) / 2;
Uppdate(nod*2,st,mid,l,r,val);
Uppdate(nod*2+1,mid+1,dr,l,r,val);
if (Tree[nod*2].st == (mid-st+1)) {
Tree[nod].st = Tree[nod*2].st + Tree[nod*2+1].st;
}
else {
Tree[nod].st = Tree[nod*2].st;
}
if (Tree[nod*2+1].dr == (dr-mid)) {
Tree[nod].dr = Tree[nod*2].dr + Tree[nod*2+1].dr;
}
else {
Tree[nod].dr = Tree[nod*2+1].dr;
}
Tree[nod].rez = std::max(std::max(Tree[nod*2].rez,Tree[nod*2+1].rez),Tree[nod*2].dr+Tree[nod*2+1].st);
}
signed main() {
int n,q;
cin>>n>>q;
for (int i=1; i<=4*n; i++) lazy[i] = -1;
Uppdate(1,1,n,1,n,0);
for (int i=1; i<=q; i++) {
int c;
cin>>c;
if (c == 1) {
int st,dr;
cin>>st>>dr;
dr += st-1;
Uppdate(1,1,n,st,dr,1);
}
if (c == 2) {
int st,dr;
cin>>st>>dr;
dr += st-1;
Uppdate(1,1,n,st,dr,0);
}
if (c == 3) {cout<<Tree[1].rez<<"\n";}
}
}