Skip to content

Slope trick

C++

template <class T = int>
struct SlopeTrick {

    SlopeTrick(T inf) : inf(inf) {
        ql.push(-inf);
        qr.push(inf);
    }

    void add_slope_l(T a) {
        // add f(x) = max(0, a-x)
        T r0 = qr.top();
        m += std::max(T(0), a - r0);

        a -= num_shift;
        qr.push(a);
        T b = qr.top();
        qr.pop();
        ql.push(b);
    }

    void add_slope_r(T a) {
        // add f(x) = max(0, x-a)
        T l0 = ql.top();
        m += std::max(T(0), l0 - a);

        a -= num_shift;
        ql.push(a);
        T b = ql.top();
        ql.pop();
        qr.push(b);
    }

    void add_const(T a) {
        // add f(x) = a
        m += a;
    }

    void shift(T a) {
        // f(x) <- f(x-a)
        num_shift += a;
    }

    void cummin_l() {
        // f(x) <- min_{y <= x} f(y)
        while (qr.size() > 1) {
            qr.pop();
        }
    }

    void cummin_r() {
        // f(x) <- min_{x <= y} f(y)
        while (ql.size() > 1) {
            ql.pop();
        }
    }

    T min() {
        // min f(x)
        return m;
    }

    T argmin() {
        // argmin f(x)
        T a = ql.top();
        if (a != -inf)
            a += num_shift;
        return a;
    }

  private:
    std::priority_queue<T, std::vector<T>, std::greater<T>> qr;
    std::priority_queue<T> ql;
    T m = 0, num_shift = 0, inf;
};

Example

Reference