// g++ meditatii.cpp -o main
// ./main
#include <bits/stdc++.h>
using namespace std;
struct Node {
long long max_len, pref_len, suf_len, lazy;
};
vector<Node> tree;
Node combine(const Node & left_child, const Node & right_child,
const int & left, const int & right, const int & mid){
Node curr_node;
curr_node.lazy = 0;
if (left_child.max_len == mid - left + 1){
curr_node.pref_len = (mid - left + 1) + right_child.pref_len;
}
else{
curr_node.pref_len = left_child.pref_len;
}
if (right_child.max_len == right - (mid+1) + 1){
curr_node.suf_len = (right - (mid+1) + 1) + left_child.suf_len;
}
else{
curr_node.suf_len = right_child.suf_len;
}
curr_node.max_len = max(max(left_child.max_len, right_child.max_len),
left_child.suf_len + right_child.pref_len);
return curr_node;
}
void propagate(const int & node, const int & left, const int & right){
if (!tree[node].lazy)
return;
if (left != right){
tree[node * 2].lazy = tree[node].lazy;
tree[node * 2 + 1].lazy = tree[node].lazy;
}
if (tree[node].lazy == 1){
// camerele se ocupa
tree[node].max_len = 0;
tree[node].pref_len = 0;
tree[node].suf_len = 0;
}
if (tree[node].lazy == -1){
// camere se elibereaza
tree[node].max_len = right - left + 1;
tree[node].pref_len = right - left + 1;
tree[node].suf_len = right - left + 1;
}
tree[node].lazy = 0;
}
void init(int node, int left, int right){
if (left == right){
// leaf
tree[node].max_len = 1;
tree[node].pref_len = 1;
tree[node].suf_len = 1;
tree[node].lazy = 0;
return;
}
int mid = (left + right) / 2;
// left subtree
init(node * 2, left , mid);
// right subtree
init(node * 2 + 1, mid + 1, right);
// combine
tree[node] = combine(tree[node * 2], tree[node * 2 + 1], left, right, mid);
}
void update(int node, int left, int right, int a, int b, int val){
propagate(node, left, right);
if (a <= left && right <= b){
tree[node].lazy = val;
return;
}
int mid = (left + right) / 2;
if (a <= mid){
update(node * 2, left, mid, a, b, val);
}
if (mid + 1 <= b){
update(node * 2 + 1, mid + 1, right, a, b, val);
}
// combine
propagate(node * 2, left, mid);
propagate(node * 2 + 1, mid + 1, right);
tree[node] = combine(tree[node * 2], tree[node * 2 + 1], left, right, mid);
}
Node query(int node, int left, int right, int a, int b){
propagate(node, left, right);
if (a <= left && right <= b){
return tree[node];
}
int mid = (left + right) / 2;
vector<Node> children;
if (a <= mid){
children.push_back(query(node * 2, left, mid, a, b));
}
if (mid + 1 <= b){
children.push_back(query(node * 2 + 1, mid + 1, right, a, b));
}
if (children.size() == 1){
return children[0];
}
return combine(children[0], children[1], left, right, mid);
}
int main() {
// freopen("input.txt", "r", stdin); freopen("output.txt", "w", stdout);
freopen("hotel.in", "r", stdin); freopen("hotel.out", "w", stdout);
int n, m;
cin>>n>>m;
// initializare
tree.resize(4*n);
init(1, 1, n);
for (int i=1; i<=m; i++){
int t;
cin>>t;
if (t == 1){
// se ocupa -> lazy = 1
int a, b;
cin>>a>>b;
update(1, 1, n, a, a+b-1, 1);
}
else if (t == 2){
// se elibereaza -> lazy = -1
int a, b;
cin>>a>>b;
update(1, 1, n, a, a+b-1, -1);
}
else if (t == 3){
// query
Node ans = query(1, 1, n, 1, n);
cout<<ans.max_len<<'\n';
}
}
return 0;
}