【模版】线段树

区间最值

  • n应作为全局变量输入!

  • 初始化建树,下标从1开始。

typedef long long ll;
const int maxn = 1e5 + 10;
ll a[maxn];
int n;
struct Segment {
    ll tr[maxn<<2], lazy[maxn<<2];
    void pushup(int o) {
        tr[o] = min(tr[o<<1], tr[o<<1|1]);
    }
    void pushdown(int o) {
        if(lazy[o]) {
            lazy[o<<1] += lazy[o];
            lazy[o<<1|1] += lazy[o];
            tr[o<<1] += lazy[o];
            tr[o<<1|1] += lazy[o];
            lazy[o] = 0;
        }
    }
    void build(int o = 1, int l = 1, int r = n) {
        lazy[o] = tr[o] = 0;
        if(l == r) {
            tr[o] = a[l];
            return ;
        }
        int m = (l + r) >> 1;
        build(o<<1, l, m);
        build(o<<1|1, m+1, r);
        pushup(o);
    }
    void update(int L, int R, ll x, int l = 1, int r = n, int o = 1) {
        if(r < L || l > R) return ;
        if(L <= l && r <= R) {
            tr[o] += x;
            lazy[o] += x;
            return ;
        }
        pushdown(o);
        int m = (l + r) >> 1;
        update(L, R, x, l, m, o<<1);
        update(L, R, x, m+1, r, o<<1|1);
        pushup(o);
    }
    ll query(int L, int R, int l = 1, int r = n, int o = 1) {
        if(r < L || l > R) return inf;
        if(L <= l && r <= R) {
            return tr[o];
        }
        pushdown(o);
        int m = (l + r) >> 1;
        return min(query(L, R, l, m, o<<1), query(L, R, m+1, r, o<<1|1));
    }
};

调用:

Segment seg;
seg.build();

__int128 z = 0;
for (int i = vec.size() - 1; i >= 0; i--) {
    int id = vec[i];
    __int128 t = seg.query(1, id); // query
    z += t * sum[id];
    seg.update(1, id, -t); // update
}
原文地址:https://www.cnblogs.com/Waldeinsamkeit/p/13444981.html