斜率优化的各种板子

维护由若干点(x, y)构成上凸包,并支持求给定一个斜率k的求通过某个点截距的最大值, 需保证 x 递增,

询问 k 递减是用query,否则用query2, 单次log(n), 判断需要用到叉积, 注意是否会爆掉LL。

斜率优化的各种板子
namespace CH {

struct Point {
    LL x, y;
    Point(LL x = 0, LL y = 0) : x(x), y(y) {}
    Point operator - (const Point &rhs) const {
        return Point(x - rhs.x, y - rhs.y);
    }
};


inline LL Det(Point A, Point B) {
    return A.x * B.y - B.x * A.y;
}

struct ConvexHull {
    Point P[N];
    int be, ed;
    void init() {
        be = 1, ed = 0;
    }
    void add(LL x, LL y) {
        Point cur(x, y);
        while(be < ed && Det(cur - P[ed], P[ed] - P[ed - 1]) <= 0) ed--;
        P[++ed] = Point(x, y);
    }
    LL query(LL k) {
        Point cur(1, k);
        while(be < ed && Det(cur, P[be + 1] - P[be]) >= 0) be++;
        return P[be].y - k * P[be].x;
    }
    LL query2(LL k) {
        Point cur(1, k);
        int low = be + 1, high = ed, mid, pos = be;
        while(low <= high) {
            mid = low + high >> 1;
            if(Det(cur, P[mid] - P[mid - 1]) >= 0) pos = mid, low = mid + 1;
            else high = mid - 1;
        }
        return P[pos].y - k * P[pos].x;
    }
};

}
View Code

 

 

维护由若干直线(y = k * x + m) 构成的下凸包,并支持给定一个 x 坐标, 求所有直线的 y 的最大值, 

没有用到叉积所以答案不怎么会爆LL。

斜率优化的各种板子
namespace LC {
/**
 * Description: Container where you can add lines of the form kx+m, and query maximum values at points x.
 * Time: O(log N)
 */
 
struct Line {
    mutable LL k, m, p;
    bool operator < (const Line& o) const { return k < o.k; }
    bool operator < (LL x) const { return p < x; }
};
 
struct LineContainer : multiset<Line, less<>> {
    // (for doubles, use inf = 1/.0, div(a,b) = a/b)
    const LL inf = LLONG_MAX;
    LL div(LL a, LL b) { // floored division
        return a / b - ((a ^ b) < 0 && a % b);
    }
    bool isect(iterator x, iterator y) {
        if (y == end()) { x->p = inf; return false; }
        if (x->k == y->k) x->p = x->m > y->m ? inf : -inf;
        else x->p = div(y->m - x->m, x->k - y->k);
        return x->p >= y->p;
    }
    void add(LL k, LL m) {
        auto z = insert({k, m, 0}), y = z++, x = y;
        while (isect(y, z)) z = erase(z);
        if (x != begin() && isect(--x, y)) isect(x, y = erase(y));
        while ((y = x) != begin() && (--x)->p >= y->p)
            isect(x, erase(y));
    }
    LL query(LL x) {
        assert(!empty());
        auto l = *lower_bound(x);
        return l.k * x + l.m;
    }
};
}
View Code

 

上一篇:433. 最小基因变化


下一篇:Graph