#include <bits/stdc++.h>
#define NUM 32768
#define OUTNUM 65536
using namespace std;
class InParser {
private:
FILE *fin;
char *buff;
int sp;
char read_ch() {
++sp;
if (sp == NUM) {
sp = 0;
fread(buff, 1, NUM, fin);
}
return buff[sp];
}
public:
InParser(const char* nume) {
fin = fopen(nume, "r");
buff = new char[NUM]();
sp = NUM - 1;
}
InParser& operator >> (int &n) {
char c;
while (!isdigit(c = read_ch()) && c != '-');
int sgn = 1;
if (c == '-') {
n = 0;
sgn = -1;
} else {
n = c - '0';
}
while (isdigit(c = read_ch())) {
n = 10 * n + c - '0';
}
n *= sgn;
return *this;
}
InParser& operator >> (long long &n) {
char c;
n = 0;
while (!isdigit(c = read_ch()) && c != '-');
long long sgn = 1;
if (c == '-') {
n = 0;
sgn = -1;
} else {
n = c - '0';
}
while (isdigit(c = read_ch())) {
n = 10 * n + c - '0';
}
n *= sgn;
return *this;
}
};
class OutParser {
private:
FILE *fout;
char *buff;
int sp;
void write_ch(char ch) {
if (sp == OUTNUM) {
fwrite(buff, 1, OUTNUM, fout);
sp = 0;
buff[sp++] = ch;
} else {
buff[sp++] = ch;
}
}
public:
OutParser(const char* name) {
fout = fopen(name, "w");
buff = new char[OUTNUM]();
sp = 0;
}
~OutParser() {
fwrite(buff, 1, sp, fout);
fclose(fout);
}
OutParser& operator << (int vu32) {
if (vu32 <= 9) {
write_ch(vu32 + '0');
} else {
(*this) << (vu32 / 10);
write_ch(vu32 % 10 + '0');
}
return *this;
}
OutParser& operator << (long long vu64) {
if (vu64 <= 9) {
write_ch(vu64 + '0');
} else {
(*this) << (vu64 / 10);
write_ch(vu64 % 10 + '0');
}
return *this;
}
OutParser& operator << (char ch) {
write_ch(ch);
return *this;
}
OutParser& operator << (const char *ch) {
while (*ch) {
write_ch(*ch);
++ch;
}
return *this;
}
};
void display_set(multiset<int> &free) {
for (auto it = free.begin(); it != free.end(); ++it) {
cout << *it << " ";
}
cout << "\n";
return;
}
void delete_interval(multiset<int> &free, int a, int b) {
//[a, b)
int l = b - a;
auto it = free.find(l);
// if (it != free.end())
free.erase(it);
// else
// cout << "something went wrong trying to delete from " << a << " to " << b << " \n";
}
void add_interval(multiset<int> &free, int a, int b) {
//[a, b)
int l = b - a;
free.insert(l);
}
void add_interval(set <pair <int, int>> &busy, multiset <int> &free, int a, int b, int n) {
// cout << "a is " << a << " and b is " << b << "\n";
if (busy.empty()) {
//we have no busy rooms presently
delete_interval(free, 1, n + 1);
busy.insert({a, b});
if (a > 1)
add_interval(free, 1, a);
if (b < n + 1)
add_interval(free, b, n + 1);
return;
}
auto after = busy.lower_bound({b, 0});
// cout << "after " << after->first << " " << after->second << "\n";
if (after == busy.end()) {
//we don't have a busy interval after our interval
auto before = --after;
// cout << "before is " << before->first << " " << before->second << "\n";
//we delete the current empty space at the right
delete_interval(free, before->second, n + 1);
//and we add the new empty space at the right
if (b < n + 1)
add_interval(free, b, n + 1);
//if the interval at the left is adjacent, we unite the intervals
if (a == before->second) {
int start = before->first;
busy.erase(before);
busy.insert({start, b});
} else {
//otherwise we add the new interval for busy rooms
// and the gap between the interval to the left and the current interval
busy.insert({a, b});
add_interval(free, before->second, a);
}
} else if (after == busy.begin()) {
//if there is no interval at the left, we delete the current gap
delete_interval(free, 1, after->first);
//and we add the new gap
if (a > 1)
add_interval(free, 1, a);
//if the interval to the right is adjacent to this interval
if (b == after->first) {
//we delete the right interval and insert the merged one
int end = after->second;
busy.erase(after);
busy.insert({a, end});
} else {
//otherwise we insert the new interval
//and the new gap
busy.insert({a, b});
add_interval(free, b, after->first);
}
} else {
//if there are neighbours on both sides, we get them
auto before = after;
--before;
//we delete the current empty space
delete_interval(free, before->second, after->first);
int start = before->first, end = after->second;
//if we want to insert an interval that fits the gap, we delete the neighbours and insert the merger
if (a == before->second && b == after->first) {
busy.erase(after);
busy.erase(before);
busy.insert({start, end});
} else if (a == before->second) {
//if the interval is adjacent only on the left
//we delete the interval on the left and insert the merger
//and we insert the right empty space
busy.erase(before);
busy.insert({start, b});
add_interval(free, b, after->first);
} else if (b == after->first) {
//if the interval is adjacent only to the right
//we delete the interval on the right and insert the merger
//and we insert the left empty space
busy.erase(after);
busy.insert({a, end});
add_interval(free, before->second, a);
} else {
//if the currentu interval isn't adjacent in any direction
//we insert the new interval
//and we insert the left and right empty spaces
busy.insert({a, b});
add_interval(free, before->second, a);
add_interval(free, b, after->first);
}
}
return;
}
void remove_interval(set <pair <int, int>> &busy, multiset <int> &free, int a, int b, int n) {
//we get the first interval that comes after the right edge of the interval
auto it = busy.lower_bound({b, 0});
//and the interval from which we will do the erasing will be the one exactly before it
auto busy_int = --it;
//we keep in mind the limits for the parent interval that will be cut
int start = busy_int->first, end = busy_int->second;
int delete_start, delete_end;
if (a == start && b == end) {
//if we need to delete the whole interval, we determine where to make the cut
if (busy_int == busy.begin()) {
//if out interval doesn't have a neighbour to the left, we will delete from the first position
delete_start = 1;
//we delete the interval from 1 to the start because it will be replaced with the big empty interval
if (a > 1)
delete_interval(free, 1, a);
} else {
//if our interval has a neighbour to the left, the left limit for the cut will be where it ends
//we delete the empty space between the interval because it will be replaced by the bigger one
auto before = busy_int;
--before;
delete_start = before->second;
delete_interval(free, before->second, a);
}
if (busy_int == --busy.end()) {
//if the don't have an interval to the right, the edge will be n + 1
//if we have an empty space to the right, we delete because it will be replaced by the big on
delete_end = n + 1;
if (b < n + 1)
delete_interval(free, b, n + 1);
} else {
//if we have a neighbour to the right, the end will be there it starts
//and we delete the empty space to the right, because it will be replaced by the big one
auto after = busy_int;
++after;
delete_interval(free, b, after->first);
delete_end = after->first;
}
add_interval(free, delete_start, delete_end);
} else if (a == start) {
//if the interval matches the parent interval only on the left
//we insert the remaining interval
busy.insert({b, end});
if (busy_int == busy.begin()) {
//if we don't have a neighbour to the left, then we delete the small empty space
//and we insert the bigger empty space, from 1 to b
if (start > 1)
delete_interval(free, 1, start);
add_interval(free, 1, b);
} else {
//otherwise, we find the left neighbour and the delete the curent empty space and insert the new one
auto before = busy_int;
--before;
delete_interval(free, before->second, a);
add_interval(free, before->second, b);
}
} else if (b == end) {
//if the interval matches the parent interval only on the right
//we insert the left remaining interval
busy.insert({start, a});
if (busy_int == --busy.end()) {
//if we don't have a neighbour to the right, we delete the current empty space
//and insert the new one
if (b < n + 1)
delete_interval(free, b, n + 1);
add_interval(free, a, n + 1);
} else {
//otherwise we get the right neighbour and we delete the current right empty space
//and we insert the new right empty space
auto after = busy_int;
++after;
delete_interval(free, b, after->first);
add_interval(free, a, after->first);
}
} else {
//if the interval is smaller on both sides than the parent interval
//we insert the remaining differences on both sides
//and we insert the empty space between a and b
busy.insert({start, a});
busy.insert({b, end});
add_interval(free, a, b);
}
//and we delete the parent interval because it has been replaced by the new bits
busy.erase(busy_int);
return;
}
int main() {
InParser fin("hotel.in");
OutParser fout("hotel.out");
int n, p; fin >> n >> p;
set <pair <int, int>> busy;
multiset <int> free;
add_interval(free, 1, n + 1);
for (int i = 0; i < p; i++) {
int t; fin >> t;
if (t == 3) {
if (free.empty())
fout << "0 \n";
else {
auto big = --free.end();
fout << *big << "\n";
}
} else if (t == 1) {
int a, b; fin >> a >> b;
add_interval(busy, free, a, a + b, n);
// cout << "dupa add \n";
// display_set(free);
} else if (t == 2) {
int a, b; fin >> a >> b;
remove_interval(busy, free, a, a + b, n);
// cout << "dupa remove \n";
// display_set(free);
}
// display_set(free);
}
return 0;
}