Hard

Amount of New Area Painted Each DayC++

Full explanation · Time O(nlogr) · Space O(r)

// Time:  O(nlogr), r is the max position
// Space: O(r)

template <typename T>
class SegmentTree {
 public:
    explicit SegmentTree(
        int N,
        const function<T(const T&, const T&)>& query_fn,
        const function<T(const T&, const T&)>& update_fn)
      : base_(N),
        tree_(2 * N),
        lazy_(2 * N),
        count_(2 * N, 1),
        query_fn_(query_fn),
        update_fn_(update_fn) {
        H_ = 1;
        while ((1 << H_) < N) {
            ++H_;
        }
        for (int i = N - 1; i >= 1; --i) {
            count_[i] = count_[2 * i] + count_[2 * i + 1];
        }
    }

    void update(int L, int R, const T& val) {
        L += base_;
        R += base_;
        push(L);  // key point
        push(R);  // key point
        int L0 = L, R0 = R;
        for (; L <= R; L >>= 1, R >>= 1) {
            if ((L & 1) == 1) {
                apply(L++, val);
            }
            if ((R & 1) == 0) {
                apply(R--, val);
            }
        }
        pull(L0);
        pull(R0);
    }

    T query(int L, int R) {
        T result{};
        if (L > R) {
            return result;
        }
        L += base_;
        R += base_;
        push(L);
        push(R);
        for (; L <= R; L >>= 1, R >>= 1) {
            if ((L & 1) == 1) {
                result = query_fn_(result, tree_[L++]);
            }
            if ((R & 1) == 0) {
                result = query_fn_(result, tree_[R--]);
            }
        }
        return result;
    }

 private:
    void apply(int x, const T val) {
        tree_[x] = update_fn_(tree_[x], val * count_[x]);
        if (x < base_) {
            lazy_[x] = update_fn_(lazy_[x], val);
        }
    }

    void pull(int x) {
        while (x > 1) {
            x >>= 1;
            tree_[x] = query_fn_(tree_[x * 2], tree_[x * 2 + 1]);
            if (lazy_[x]) {
                tree_[x] = update_fn_(tree_[x], lazy_[x] * count_[x]);
            }
        }
    }

    void push(int x) {
       for (int h = H_; h > 0; --h) {
           int y = x >> h;
           if (lazy_[y]) {
                apply(y * 2, lazy_[y]);
                apply(y * 2 + 1, lazy_[y]);
                lazy_[y] = 0;
            }
        }
    }

    int base_;
    int H_;
    vector<T> tree_;
    vector<T> lazy_;
    vector<T> count_;
    const function<T(const T&, const T&)> query_fn_;
    const function<T(const T&, const T&)> update_fn_;
};

// segment tree
class Solution {
public:
    vector<int> amountPainted(vector<vector<int>>& paint) {
        const auto& query = [] (const auto& x, const auto& y) {
            return x + y;
        };
        const auto& update = [] (const auto& x, const auto& y) {
            return y;
        };
        const int max_pos = (*max_element(cbegin(paint), cend(paint),
            [](const auto& x, const auto& y) { return x[1] < y[1]; }
        ))[1];
        SegmentTree<int> st(max_pos, query, update);
        vector<int> result;
        for (const auto& x : paint) {
            const int cnt = st.query(x[0], x[1] - 1);
            st.update(x[0], x[1] - 1, 1);
            result.emplace_back(st.query(x[0], x[1] - 1) - cnt);
        }
        return result;
    }
};

// Time:  O(nlogn)
// Space: O(n)
// line sweep, heap
class Solution2 {
public:
    vector<int> amountPainted(vector<vector<int>>& paint) {
        map<int, vector<pair<int, int>>> points;
        for (int i = 0; i < size(paint); ++i) {
            points[paint[i][0]].emplace_back(1, i);
            points[paint[i][1]].emplace_back(0, i);
        }
        priority_queue<int, vector<int>, greater<int>> min_heap;
        vector<bool> lookup(size(paint));
        vector<int> result(size(paint));
        int prev = -1;
        for (const auto& [pos, v] : points) {
             while (!empty(min_heap) && lookup[min_heap.top()]) {
                min_heap.pop();
            }
            if (!empty(min_heap)) {
                result[min_heap.top()] += pos - prev;
            }
            prev = pos;
            for (const auto& [t, i] : v) {
                if (t) {
                    min_heap.emplace(i);
                } else {
                    lookup[i] = true;
                }
            }
        }
        return result;
    }
};

// Time:  O(nlogn)
// Space: O(n)
// line sweep, bst
class Solution3 {
public:
    vector<int> amountPainted(vector<vector<int>>& paint) {
        map<int, vector<pair<int, int>>> points;
        for (int i = 0; i < size(paint); ++i) {
            points[paint[i][0]].emplace_back(1, i);
            points[paint[i][1]].emplace_back(0, i);
        }
        set<int> bst;
        vector<int> result(size(paint));
        int prev = -1;
        for (const auto& [pos, v] : points) {
            if (!empty(bst)) {
                result[*begin(bst)] += pos - prev;
            }
            prev = pos;
            for (const auto& [t, i] : v) {
                if (t) {
                    bst.emplace(i);
                } else {
                    bst.erase(i);
                }
            }            
        }
        return result;
    }
};