#include <fstream>
#include <iostream>
#define N 100010
std::ifstream fin("hotel.in");
std::ofstream fout("hotel.out");
int n, Lazy[4*N] = {-1}, Q;
struct Node{
int left, right, mx;
Node() : left(0), right(0), mx(0) {};
Node(int elem) : left(elem), right(elem), mx(elem) {};
friend std::ostream& operator <<(std::ostream& fout, const Node& Obj){
fout << Obj.left << " " << Obj.right << " " << Obj.mx << "\n";
return fout;
}
} Tree[4*N];
void basicUpdate(int node, int left, int right, int pos, int elem);
Node unite(Node first, Node second, int L, int R){
Node rez;
rez.left = first.left;
if(first.left == L)
rez.left += second.left;
rez.right = second.right;
if(second.right == R)
rez.right += first.right;
int dist = first.right + second.left;
rez.mx = std::max(rez.left, std::max(rez.right, std::max(first.mx, std::max(second.mx, dist))));
return rez;
}
void updateInt(int node, int left, int right, int L, int R, int diff){
if(Lazy[node] != -1){//propagate
Tree[node].left = Tree[node].right = Tree[node].mx = (right - left + 1)*Lazy[node];
if(left != right){
Lazy[2*node] = Lazy[node];
Lazy[2*node + 1] = Lazy[node];
}
Lazy[node] = -1;
}
if(left > R || right < L)
return;
if(L <= left && right <= R){
Tree[node].left = Tree[node].right = Tree[node].mx = (right - left + 1)*diff;
if(left != right ){
Lazy[2*node] = diff;
Lazy[2*node + 1] = diff;
}
return;
}
int mid = left + (right - left)/2;
updateInt(node*2, left, mid, L, R, diff);
updateInt(node*2 + 1, mid + 1, right, L, R, diff);
Tree[node] = unite(Tree[node*2], Tree[node*2 + 1], mid - left + 1, right - mid);
}
Node queryInt(int node, int left, int right, int L, int R){
if(Lazy[node] != -1){//propagate
Tree[node].left = Tree[node].right = Tree[node].mx = (right - left + 1)*Lazy[node];
if(left != right){
Lazy[2*node] = Lazy[node];
Lazy[2*node + 1] = Lazy[node];
}
Lazy[node] = -1;
}
if( left > R || right < L)
return Node();
if(L <= left && right <= R){
return Tree[node];
}
int mid = left + (right - left)/2;
return unite(queryInt(node*2, left, mid, L, R),
queryInt(node*2 + 1, mid + 1, right, L, R), mid - left + 1, right - mid);
}
/*std::pair<int,int> ind[4*N];
void indx( int nod, int l, int r ){
ind[nod].first = l;
ind[nod].second = r;
if( l != r ){
int mid = l + (r - l)/2;
indx( nod*2, l, mid);
indx( nod*2+1, mid+1, r);
}
}*/
void printTree(){
for(int j=0; (1 << (j-1)) <= n; j++){
for(int i = (1<<j); i <= (1<<(j+1)) -1; i++){
// fout << "(" << Tree[i].mx << "-" << ind[i].first << "," << ind[i].second << ") ";
}
fout << "\n";
}
}
int main(){
int P;
fin >> n >> P;
updateInt(1, 1, n, 1, n, 1);
//indx(1, 1, n);
//fout << "\n";
//printTree();
for(int i=1; i<=P; i++){
int op;
fin >> op ;
if(op == 1){
int x, m;
fin >> x >> m;
updateInt(1, 1, n, x, x + m - 1, 0);
//fout << "\n" << x << " " << x + m - 1 <<"0 \n";
//printTree();
}
else if(op == 2){
int x, m;
fin >> x >> m;
updateInt(1, 1, n, x, x + m - 1, 1);
//fout << "\n" << x << " " << x + m - 1 <<"1 \n";
//printTree();
}
else if(op == 3){
fout << queryInt(1, 1, n, 1, n).mx << "\n";
}
}
//fout << "\n";
//printTree();
return 0;
}
void basicUpdate(int node, int left, int right, int pos, int elem){
if(left == right && left == pos){
Tree[node] = Node(elem);
return;
}
int mid = left + (right - left)/2;
if(pos <= mid){
basicUpdate(node*2, left, mid, pos, elem);
}
else{
basicUpdate(node*2 + 1, mid + 1, right, pos, elem);
}
Tree[node] = unite(Tree[node*2], Tree[node*2 + 1], mid - left + 1, right - mid);
}