#include <fstream>
#include <iostream>
using namespace std;
const int N = 1 << 17;
template<class Node, Node (*comp)(Node, Node), class Lazy, Node (*apply)(Node, int, int, Lazy), Lazy (*comp_lazy)(Lazy, Lazy)>
class Aint{
Node aint[2 * N], n_zero, acc;
Lazy lz[N], l_zero;
void lazy_update(int pos, int st, int dr, Lazy L){
if ( st == dr )
aint[pos] = apply( aint[pos], st, dr, L);
else
lz[pos] = comp_lazy( lz[pos], L );
}
inline Node arbint(int pos, int st, int dr){
if ( st == dr ) return aint[pos];
aint[pos] = apply(aint[pos], st, dr, lz[pos]);
int m = (st + dr) >> 1;
lazy_update( 2 * pos, st, m, lz[pos] );
lazy_update( 2 * pos + 1, m + 1, dr, lz[pos] );
lz[pos] = l_zero;
return aint[pos];
}
void update(int pos, int st, int dr, int x, int y, Lazy L){
if ( x <= st && dr <= y )
return lazy_update(pos, st, dr, L);
arbint(pos, st, dr);
int m = (st + dr) >> 1;
if ( x <= m )
update(2 * pos, st, m, x, y, L);
if ( m < y )
update(2 * pos + 1, m + 1, dr, x, y, L);
aint[pos] = comp( arbint(2 * pos, st, m), arbint(2 * pos + 1, m + 1, dr) );
}
void query(int pos, int st, int dr, int x, int y){
arbint(pos, st, dr);
if ( x <= st && dr <= y ){
acc = comp( acc, aint[pos] );
return;
}
int m = (st + dr) >> 1;
if ( x <= m )
query(2 * pos, st, m, x, y);
if ( m < y )
query(2 * pos + 1, m + 1, dr, x, y);
}
public:
Aint(Node n_zero, Lazy l_zero) : n_zero(n_zero), l_zero(l_zero) {
for (int i = 0; i < 2 * N; i++) aint[i] = n_zero;
for (int i = 0; i < N; i++) lz[i] = l_zero;
}
void update(int x, int y, Lazy L){
return update(1, 1, N, x, y, L);
}
void update(int x, Lazy L){
return update(x, x, L);
}
Node query(int x, int y){
acc = n_zero;
query(1, 1, N, x, y);
return acc;
}
pair<int, Node> greedy(Node target, bool (*cmp)(Node, Node)){
if ( cmp(aint[1], target) )
return make_pair( N, arbint(1, 1, N) );
int pos = 1, st = 1, dr = N;
Node ans = n_zero;
while (st != dr){
int m = (st + dr) >> 1;
pos <<= 1;
Node part = comp( ans, arbint(pos, st, m) );
if ( cmp(part, target) ){
ans = part;
st = m + 1;
pos++;
} else
dr = m;
}
return make_pair(st - 1, ans);
}
};
struct Node{
int S, C, D;
bool T;
Node (int S = 0, int C = 0, int D = 0, bool T = 0) : S(S), C(C), D(D), T(T) {};
};
inline int max(int a, int b, int c){
return max( a, max(b, c) );
}
Node combine(Node a, Node b){
return Node( (a.T ? a.C + b.S : a.S), max(a.C, b.C, a.D + b.S), (b.T ? a.D + b.C : b.D), a.T && b.T );
}
char ovrw(char a, char b){
return b ? b : a;
}
Node apply(Node n, int x, int y, char upd){
if ( upd == -1 )
return Node(0, 0, 0, false);
if ( upd == 0 )
return n;
int a = y - x + 1;
return Node(a, a, a, true);
}
Aint<Node, combine, char, apply, ovrw> A( Node(0, 0, 0, true), 0);
int main(){
int n, times, tip, x, y;
ifstream in("hotel.in");
ofstream out("hotel.out");
in >> n >> times;
A.update(1, n, 1);
A.update(n + 1, N, -1);
while (times--){
in >> tip;
if ( tip == 3 ){
out << A.query(1, n).C << '\n';
continue;
}
in >> x >> y;
A.update(x, x + y - 1, tip == 1 ? -1 : 1);
}
return 0;
}