李超线段树

李超线段树

性质:李超线段树一般支持具有单调性的函数,如一次函数。

1、李超求该位置包含的所有函数的 \(min\)

template<typename T>
struct LC_tree{
    T eps = 1e-15;
    struct line{
        T k, b;
        line(T k = 0.0, T b = 1e18) : k(k), b(b) {}
        #define ls (root << 1)
        #define rs (root << 1 | 1)
    };

    int cnt, n;
    vector<line> tree;
    LC_tree(int n_) : tree(n_ << 2) {
        n = n_;
    }

    inline int cmp(T x, T y) {
        if (x - y > eps) return 1;
        else if (y - x > eps) return -1;
        return 0;
    }

    inline T calc(T x, const line &kb) {
        T sum = x * kb.k + kb.b;
        return sum;
    }

    inline void upd(int root, int l, int r, line kb) {
        int mid = l + r >> 1;
        auto &rt = tree[root];
        int cn = cmp(calc(mid, kb), calc(mid, rt));
        if (cn == -1) swap(rt, kb);
        int cnl = cmp(calc(l, kb), calc(l, rt)), cnr = cmp(calc(r, kb), calc(r, rt));
        if (cnl == -1) upd(ls, l, mid, kb);
        if (cnr == -1) upd(rs, mid + 1, r, kb);
    }

    inline void update(int root, int l, int r, int ql, int qr, const line &kb) {
        int mid = l + r >> 1;
        if (ql > r || qr < l) return;
        if (l >= ql && r <= qr) {
            upd(root, l, r, kb);
            return;
        }
        update(ls, l, mid, ql, qr, kb);
        update(rs, mid + 1, r, ql, qr, kb);
    }

    inline T query(int root, int l, int r, int pos) {
        T ans = calc(pos, tree[root]);
        if (l == r) return ans;
        int mid = l + r >> 1;
        if (pos <= mid) ans = min(ans, query(ls, l, mid, pos));
        else ans = min(ans, query(rs, mid + 1, r, pos));
        return ans;
    }
};

2、李超求该位置包含的所有函数的 \(max\)

template<typename T>
struct LC_tree{
    T eps = 1e-15;
    struct line{
        T k, b;
        line(T k = 0.0, T b = -1e18) : k(k), b(b) {}
        #define ls (root << 1)
        #define rs (root << 1 | 1)
    };

    int cnt, n;
    vector<line> tree;
    LC_tree(int n_) : tree(n_ << 2) {
        n = n_;
    }

    inline int cmp(T x, T y) {
        if (x - y > eps) return 1;
        else if (y - x > eps) return -1;
        return 0;
    }

    inline T calc(T x, const line &kb) {
        T sum = x * kb.k + kb.b;
        return sum;
    }

    inline void upd(int root, int l, int r, line kb) {
        int mid = l + r >> 1;
        auto &rt = tree[root];
        int cn = cmp(calc(mid, kb), calc(mid, rt));
        if (cn == 1) swap(rt, kb);
        int cnl = cmp(calc(l, kb), calc(l, rt)), cnr = cmp(calc(r, kb), calc(r, rt));
        if (cnl == 1) upd(ls, l, mid, kb);
        if (cnr == 1) upd(rs, mid + 1, r, kb);
    }

    inline void update(int root, int l, int r, int ql, int qr, const line &kb) {
        int mid = l + r >> 1;
        if (ql > r || qr < l) return;
        if (l >= ql && r <= qr) {
            upd(root, l, r, kb);
            return;
        }
        update(ls, l, mid, ql, qr, kb);
        update(rs, mid + 1, r, ql, qr, kb);
    }

    inline T query(int root, int l, int r, int pos) {
        T ans = calc(pos, tree[root]);
        if (l == r) return ans;
        int mid = l + r >> 1;
        if (pos <= mid) ans = max(ans, query(ls, l, mid, pos));
        else ans = max(ans, query(rs, mid + 1, r, pos));
        return ans;
    }
};

3、例题一:洛谷P11014

template<typename T>
struct LC_tree{
    T eps = 1e-15;
    struct line{
        T k, b;
        line(T k = 0.0, T b = 1e18) : k(k), b(b) {}
        #define ls (root << 1)
        #define rs (root << 1 | 1)
    };

    int cnt, n;
    vector<line> tree;
    LC_tree(int n_) : tree(n_ << 2) {
        n = n_;
    }

    inline int cmp(T x, T y) {
        if (x - y > eps) return 1;
        else if (y - x > eps) return -1;
        return 0;
    }

    inline T calc(T x, const line &kb) {
        T sum = x * kb.k + kb.b;
        return sum;
    }

    inline void upd(int root, int l, int r, line kb) {
        int mid = l + r >> 1;
        auto &rt = tree[root];
        int cn = cmp(calc(mid, kb), calc(mid, rt));
        if (cn == -1) swap(rt, kb);
        int cnl = cmp(calc(l, kb), calc(l, rt)), cnr = cmp(calc(r, kb), calc(r, rt));
        if (cnl == -1) upd(ls, l, mid, kb);
        if (cnr == -1) upd(rs, mid + 1, r, kb);
    }

    inline void update(int root, int l, int r, int ql, int qr, const line &kb) {
        int mid = l + r >> 1;
        if (ql > r || qr < l) return;
        if (l >= ql && r <= qr) {
            upd(root, l, r, kb);
            return;
        }
        update(ls, l, mid, ql, qr, kb);
        update(rs, mid + 1, r, ql, qr, kb);
    }

    inline T query(int root, int l, int r, int pos) {
        T ans = calc(pos, tree[root]);
        if (l == r) return ans;
        int mid = l + r >> 1;
        if (pos <= mid) ans = min(ans, query(ls, l, mid, pos));
        else ans = min(ans, query(rs, mid + 1, r, pos));
        return ans;
    }
};

struct pre{
    int N;
    vector<i64> preim;
    vector<i64> a;
    vector<i64> val;
    pre(int N_) : a(N_ + 1), val(N_ + 1) {
        N = N_;
        for (i64 i = 2; i <= N; i++) {
            if (!a[i]) {
                a[i] = i;
                val[i] = i;
                preim.push_back(i);
            }
            for (auto p : preim) {
                if (i * p > N) break;
                a[i * p] = p;
                if (a[i] == p) {
                    val[i * p] = val[i];
                    break;
                }
                val[i * p] = val[i] + p;
            }
        }
    }
    
    inline bool ispreim(int x) { return (a[x] == x && x != 0); }
};

pre t(N + 1);

void solve() {
    LC_tree<long double> tr(2e5);
    int n;
    long double m1, k;
    cin >> n >> m1 >> k;
    vector<long double> m(n + 1), val(n + 1);
    vector<i64> w(n + 1);
    for (int i = 1; i <= n; i++) {
        cin >> w[i];
        val[i] = t.val[w[i]];
    }
    m[1] = m1;
    for (int i = 1; i <= n; i++) {
        if (i > 1) m[i] = 1.0 / tr.query(1, 1, 2e5, val[i]) + k;
        long double k1 = 1.0 / m[i], b1 = val[i] / m[i];
        tr.upd(1, 1, 2e5, {k1, b1});
    }
    long double ans = 0;
    for (int i = 1; i <= n; i++) {
        ans += m[i];
    }
    printf("%.10Lf\n", ans);
}

4、例题二(强制在线):洛谷P4097

posted @ 2024-08-15 02:42  grape_king  阅读(18)  评论(0)    收藏  举报