Youthful-Passion-Fruit-teambook

This documentation is automatically generated by online-judge-tools/verification-helper

View the Project on GitHub AlexanderNekrasov/Youthful-Passion-Fruit-teambook

:warning: geometry/Kinetic.cpp

Code

/**
 * Author: Alexey Vasilyev
 * Date: 2024-08-20
 * Description: kinetic segment tree
 * Time: O(hz)
 */
//vnutrennii functions - poluintervali, vneshnie - otrezki. ishet min priamuy
struct line {
    ll k,b,temp;
    ll eval() const {
        return k * temp + b;
    }
    ll melting_point(const line& other) const {
        ll val1 = eval();
        ll val2 = other.eval();
        assert(val1 <= val2);
        if (other.k >= k) {
            return INF;
        }
        ll delta_val = val2 - val1;
        ll delta_k = k - other.k;
        assert(delta_val >= 0 && delta_k > 0);
        return (delta_val + delta_k - 1) / delta_k;
    }
};
struct kinetic_segtree {
    struct node {
        ll lazy_b = 0, lazy_temp = 0, melt = INF;
        line best;
        node(line best = line()) : best(best) {}
    };
    int n;
    vector<node> tree;
    void update(int v) {
        if (make_pair(tree[v << 1].best.eval(), tree[v << 1].best.k) < make_pair(tree[v << 1 | 1].best.eval(), tree[v << 1 | 1].best.k)) {
            tree[v].best = tree[v << 1].best;
            tree[v].melt = tree[v].best.melting_point(tree[v << 1 | 1].best);
        } else {
            tree[v].best = tree[v << 1 | 1].best;
            tree[v].melt = tree[v].best.melting_point(tree[v << 1].best);
        }

        tree[v].melt = min({tree[v].melt, tree[v << 1].melt, tree[v << 1 | 1].melt});
        assert(tree[v].melt > 0);
    }
    void apply(int v, int vl, int vr, ll delta_b, ll delta_temp) {
        tree[v].lazy_b += delta_b;
        tree[v].lazy_temp += delta_temp;

        tree[v].best.b += delta_b;
        tree[v].best.temp += delta_temp;

        tree[v].melt -= delta_temp;
        if (tree[v].melt <= 0) {
            push(v, vl, vr);
            update(v);
        }
    }
    void push(int v, int vl, int vr) {
        int vm = (vl + vr) / 2;
        apply(v << 1, vl, vm, tree[v].lazy_b, tree[v].lazy_temp);
        apply(v << 1 | 1, vm, vr, tree[v].lazy_b, tree[v].lazy_temp);
        tree[v].lazy_b = 0;
        tree[v].lazy_temp = 0;
    }
    void build(int v, int vl, int vr, const vector<line> &lines) {
        if (vr - vl == 1) {
            tree[v] = node(lines[vl]);
            return;
        }
        int vm = (vl + vr) / 2;
        build(v << 1, vl, vm, lines);
        build(v << 1 | 1, vm, vr, lines);
        update(v);
    }
    void add(int v, int vl, int vr, int l, int r, ll delta_b, ll delta_temp) {
        if (r <= vl || vr <= l) {
            return;
        }
        if (l <= vl && vr <= r) {
            apply(v, vl, vr, delta_b, delta_temp);
            return;
        }
        push(v, vl, vr);
        int vm = (vl + vr) / 2;
        add(v << 1, vl, vm, l, r, delta_b, delta_temp);
        add(v << 1 | 1, vm, vr, l, r, delta_b, delta_temp);
        update(v);
    }
    void change_line(int v, int vl, int vr, int pos, const line &new_line) {
        if (vr - vl == 1) {
            tree[v].best = new_line;
            return;
        }
        push(v, vl, vr);
        int vm = (vl + vr) / 2;
        if (pos < vm) {
            change_line(v << 1, vl, vm, pos, new_line);
        } else {
            change_line(v << 1 | 1, vm, vr, pos, new_line);
        }
        update(v);
    }
    ll query(int v, int vl, int vr, int l, int r) {
        if (r <= vl || vr <= l) {
            return INF;
        }
        if (l <= vl && vr <= r) {
            return tree[v].best.eval();
        }
        push(v, vl, vr);
        int vm = (vl + vr) / 2;
        return min(query(v << 1, vl, vm, l, r), query(v << 1 | 1, vm, vr, l, r));
    }
    kinetic_segtree(const vector<line> &lines) : n(lines.size()), tree(4 * n) {
        build(1, 0, n, lines);
    }
    kinetic_segtree(int n) : n(n), tree(4 * n) {
        vector <line> lines(n, {0, INF, 0});
        build(1, 0, n, lines);
    }
    void add(int l, int r, ll delta_b, ll delta_temp) {
        assert(delta_temp >= 0);
        add(1, 0, n, l, r + 1, delta_b, delta_temp);
    }
    void change_line(int pos, const line &new_line) {
        assert(0 <= pos && pos < n);
        change_line(1, 0, n, pos, new_line);
    }
    ll query(int l, int r) {
        return query(1, 0, n, l, r + 1);
    }
}
#line 1 "geometry/Kinetic.cpp"
/**
 * Author: Alexey Vasilyev
 * Date: 2024-08-20
 * Description: kinetic segment tree
 * Time: O(hz)
 */
//vnutrennii functions - poluintervali, vneshnie - otrezki. ishet min priamuy
struct line {
    ll k,b,temp;
    ll eval() const {
        return k * temp + b;
    }
    ll melting_point(const line& other) const {
        ll val1 = eval();
        ll val2 = other.eval();
        assert(val1 <= val2);
        if (other.k >= k) {
            return INF;
        }
        ll delta_val = val2 - val1;
        ll delta_k = k - other.k;
        assert(delta_val >= 0 && delta_k > 0);
        return (delta_val + delta_k - 1) / delta_k;
    }
};
struct kinetic_segtree {
    struct node {
        ll lazy_b = 0, lazy_temp = 0, melt = INF;
        line best;
        node(line best = line()) : best(best) {}
    };
    int n;
    vector<node> tree;
    void update(int v) {
        if (make_pair(tree[v << 1].best.eval(), tree[v << 1].best.k) < make_pair(tree[v << 1 | 1].best.eval(), tree[v << 1 | 1].best.k)) {
            tree[v].best = tree[v << 1].best;
            tree[v].melt = tree[v].best.melting_point(tree[v << 1 | 1].best);
        } else {
            tree[v].best = tree[v << 1 | 1].best;
            tree[v].melt = tree[v].best.melting_point(tree[v << 1].best);
        }

        tree[v].melt = min({tree[v].melt, tree[v << 1].melt, tree[v << 1 | 1].melt});
        assert(tree[v].melt > 0);
    }
    void apply(int v, int vl, int vr, ll delta_b, ll delta_temp) {
        tree[v].lazy_b += delta_b;
        tree[v].lazy_temp += delta_temp;

        tree[v].best.b += delta_b;
        tree[v].best.temp += delta_temp;

        tree[v].melt -= delta_temp;
        if (tree[v].melt <= 0) {
            push(v, vl, vr);
            update(v);
        }
    }
    void push(int v, int vl, int vr) {
        int vm = (vl + vr) / 2;
        apply(v << 1, vl, vm, tree[v].lazy_b, tree[v].lazy_temp);
        apply(v << 1 | 1, vm, vr, tree[v].lazy_b, tree[v].lazy_temp);
        tree[v].lazy_b = 0;
        tree[v].lazy_temp = 0;
    }
    void build(int v, int vl, int vr, const vector<line> &lines) {
        if (vr - vl == 1) {
            tree[v] = node(lines[vl]);
            return;
        }
        int vm = (vl + vr) / 2;
        build(v << 1, vl, vm, lines);
        build(v << 1 | 1, vm, vr, lines);
        update(v);
    }
    void add(int v, int vl, int vr, int l, int r, ll delta_b, ll delta_temp) {
        if (r <= vl || vr <= l) {
            return;
        }
        if (l <= vl && vr <= r) {
            apply(v, vl, vr, delta_b, delta_temp);
            return;
        }
        push(v, vl, vr);
        int vm = (vl + vr) / 2;
        add(v << 1, vl, vm, l, r, delta_b, delta_temp);
        add(v << 1 | 1, vm, vr, l, r, delta_b, delta_temp);
        update(v);
    }
    void change_line(int v, int vl, int vr, int pos, const line &new_line) {
        if (vr - vl == 1) {
            tree[v].best = new_line;
            return;
        }
        push(v, vl, vr);
        int vm = (vl + vr) / 2;
        if (pos < vm) {
            change_line(v << 1, vl, vm, pos, new_line);
        } else {
            change_line(v << 1 | 1, vm, vr, pos, new_line);
        }
        update(v);
    }
    ll query(int v, int vl, int vr, int l, int r) {
        if (r <= vl || vr <= l) {
            return INF;
        }
        if (l <= vl && vr <= r) {
            return tree[v].best.eval();
        }
        push(v, vl, vr);
        int vm = (vl + vr) / 2;
        return min(query(v << 1, vl, vm, l, r), query(v << 1 | 1, vm, vr, l, r));
    }
    kinetic_segtree(const vector<line> &lines) : n(lines.size()), tree(4 * n) {
        build(1, 0, n, lines);
    }
    kinetic_segtree(int n) : n(n), tree(4 * n) {
        vector <line> lines(n, {0, INF, 0});
        build(1, 0, n, lines);
    }
    void add(int l, int r, ll delta_b, ll delta_temp) {
        assert(delta_temp >= 0);
        add(1, 0, n, l, r + 1, delta_b, delta_temp);
    }
    void change_line(int pos, const line &new_line) {
        assert(0 <= pos && pos < n);
        change_line(1, 0, n, pos, new_line);
    }
    ll query(int l, int r) {
        return query(1, 0, n, l, r + 1);
    }
}
Back to top page