【模版】线段树
区间最值
-
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
}