LeetCode Solutions
715. Range Module
Time: Constructor: $O(1)$, addRange(left: int, right: int): $O(\log 10^9)$, queryRange(left: int, right: int): $O(\log 10^9)$, removeRange(left: int, right: int): $O(\log 10^9)$ Space: $O(n)$
struct SegmentTreeNode {
int lo;
int hi;
bool tracked = false;
SegmentTreeNode* left;
SegmentTreeNode* right;
SegmentTreeNode(int lo, int hi, bool tracked, SegmentTreeNode* left = nullptr,
SegmentTreeNode* right = nullptr)
: lo(lo), hi(hi), tracked(tracked), left(left), right(right) {}
~SegmentTreeNode() {
delete left;
delete right;
left = nullptr;
right = nullptr;
}
};
class SegmentTree {
public:
SegmentTree() : root(make_unique<SegmentTreeNode>(0, 1e9, false)) {}
void addRange(int i, int j) {
update(root.get(), i, j, true);
}
bool queryRange(int i, int j) {
return query(root.get(), i, j);
}
void removeRange(int i, int j) {
update(root.get(), i, j, false);
}
private:
std::unique_ptr<SegmentTreeNode> root;
void update(SegmentTreeNode* root, int i, int j, bool tracked) {
if (root->lo == i && root->hi == j) {
root->tracked = tracked;
root->left = nullptr;
root->right = nullptr;
return;
}
const int mid = root->lo + (root->hi - root->lo) / 2;
if (root->left == nullptr) {
root->left = new SegmentTreeNode(root->lo, mid, root->tracked);
root->right = new SegmentTreeNode(mid + 1, root->hi, root->tracked);
}
if (j <= mid)
update(root->left, i, j, tracked);
else if (i > mid)
update(root->right, i, j, tracked);
else {
update(root->left, i, mid, tracked);
update(root->right, mid + 1, j, tracked);
}
root->tracked = root->left->tracked && root->right->tracked;
}
bool query(SegmentTreeNode* root, int i, int j) {
if (root->left == nullptr)
return root->tracked;
if (root->lo == i && root->hi == j)
return root->tracked;
const int mid = root->lo + (root->hi - root->lo) / 2;
if (j <= mid)
return query(root->left, i, j);
if (i > mid)
return query(root->right, i, j);
return query(root->left, i, mid) && query(root->right, mid + 1, j);
}
};
class RangeModule {
public:
void addRange(int left, int right) {
tree.addRange(left, right - 1);
}
bool queryRange(int left, int right) {
return tree.queryRange(left, right - 1);
}
void removeRange(int left, int right) {
tree.removeRange(left, right - 1);
}
private:
SegmentTree tree;
};
class RangeModule {
public:
void addRange(int left, int right) {
const auto [l, r] = getOverlapRanges(left, right);
if (l == r) { // No overlaps
ranges[left] = right; // Add a new range
return;
}
auto last = r;
const int newLeft = min(l->first, left);
const int newRight = max((--last)->second, right);
ranges.erase(l, r);
ranges[newLeft] = newRight; // Add a new range
}
bool queryRange(int left, int right) {
auto it = ranges.upper_bound(left);
return it != begin(ranges) && (--it)->second >= right;
}
void removeRange(int left, int right) {
const auto [l, r] = getOverlapRanges(left, right);
if (l == r) // No overlaps
return;
auto last = r;
const int newLeft = min(l->first, left);
const int newRight = max((--last)->second, right);
ranges.erase(l, r);
// Add new ranges if needed
if (newLeft < left)
ranges[newLeft] = left;
if (right < newRight)
ranges[right] = newRight;
}
private:
using IT = map<int, int>::iterator;
map<int, int> ranges;
pair<IT, IT> getOverlapRanges(int left, int right) {
// Point to 1st element with second >= than left
IT l = ranges.upper_bound(left);
// Point to 1st element with first > than right
IT r = ranges.upper_bound(right);
if (l != begin(ranges) && (--l)->second < left)
++l;
return {l, r};
}
};
class RangeModule {
public void addRange(int left, int right) {
Integer l = ranges.floorKey(left);
Integer r = ranges.floorKey(right);
if (l != null && ranges.get(l) >= left)
left = l;
if (r != null && ranges.get(r) > right)
right = ranges.get(r);
ranges.subMap(left, right).clear();
ranges.put(left, right);
}
public boolean queryRange(int left, int right) {
Integer l = ranges.floorKey(left);
return l == null ? false : ranges.get(l) >= right;
}
public void removeRange(int left, int right) {
Integer l = ranges.floorKey(left);
Integer r = ranges.floorKey(right);
if (r != null && ranges.get(r) > right)
ranges.put(right, ranges.get(r));
if (l != null && ranges.get(l) > left)
ranges.put(l, left);
ranges.subMap(left, right).clear();
}
private TreeMap<Integer, Integer> ranges = new TreeMap<>();
}