|
| 1 | +class MyCalendarTwo { |
| 2 | + // map of start->end, each entry represents an interval [start, end) |
| 3 | + // singleBooked is a superset of double booked, we don't have to worry about the double booked parts of it because we'll early return anyway. |
| 4 | + std::map<int, int> singleBooked, doubleBooked; |
| 5 | +public: |
| 6 | + |
| 7 | + MyCalendarTwo() {} |
| 8 | + |
| 9 | + bool book(int start, int end) { |
| 10 | + { // if [start, end) overlaps any double booked interval, we cannot insert. |
| 11 | + const auto after = doubleBooked.lower_bound(end); |
| 12 | + if(after != doubleBooked.begin()) { |
| 13 | + const auto iter = std::prev(after); |
| 14 | + if(iter->second > start) return false; |
| 15 | + } |
| 16 | + } |
| 17 | + |
| 18 | + // find all intervals that overlap with this one. |
| 19 | + // for each of those intervals, add the intersection of it and the current one to the doubleBooked interval set. |
| 20 | + auto iter = singleBooked.upper_bound(start); |
| 21 | + if(iter != singleBooked.begin() && (std::prev(iter)->second > start)) --iter; |
| 22 | + const auto startIter = iter; |
| 23 | + while(iter != singleBooked.end() && iter->first < end) { |
| 24 | + doubleBooked[std::max(start, iter->first)] = std::min(end, iter->second); |
| 25 | + ++iter; |
| 26 | + } |
| 27 | + const auto endIter = iter; |
| 28 | + |
| 29 | + // merge all overlapping intervals in singleBooked into one big interval. |
| 30 | + int newStart = start; |
| 31 | + int newEnd = end; |
| 32 | + if(startIter != singleBooked.end()) newStart = min(start, startIter->first); |
| 33 | + if(endIter != singleBooked.begin()) newEnd = max(newEnd, std::prev(endIter)->second); |
| 34 | + const auto afterErase = singleBooked.erase(startIter, endIter); |
| 35 | + singleBooked.emplace_hint(afterErase, newStart, newEnd); |
| 36 | + return true; |
| 37 | + } |
| 38 | +}; |
0 commit comments