区间加法
struct SegmentTree {
#define ls (u << 1)
#define rs (u << 1 | 1)
#define mid ((l + r) >> 1)
static const int MAXN = 2e5 + 10;
static const ll LINF = 1e18 + 10;
ll tag[MAXN << 2];
ll mi[MAXN << 2];
ll mx[MAXN << 2];
ll sum[MAXN << 2];
void PushUp(int u) {
mi[u] = min(mi[ls], mi[rs]);
mx[u] = max(mx[ls], mx[rs]);
sum[u] = sum[ls] + sum[rs];
}
void PushDown(int u, int l, int r) {
ll t = tag[u];
if(t != 0) {
tag[ls] += t, mi[ls] += t, mx[ls] += t;
sum[ls] += 1LL * (mid - l + 1) * t;
tag[rs] += t, mi[rs] += t, mx[rs] += t;
sum[rs] += 1LL * (r - mid) * t;
tag[u] = 0;
}
}
void Build(int u, int l, int r) {
tag[u] = 0;
if(l == r) {
mi[u] = mx[u] = sum[u] = 0;
return;
}
Build(ls, l, mid);
Build(rs, mid + 1, r);
PushUp(u);
}
void UpdateAdd(int u, int l, int r, int L, int R, ll v) {
if(L <= l && r <= R) {
tag[u] += v, mi[u] += v, mx[u] += v;
sum[u] += 1LL * (r - l + 1) * v;
return;
}
PushDown(u, l, r);
if(L <= mid) UpdateAdd(ls, l, mid, L, R, v);
if(R >= mid + 1) UpdateAdd(rs, mid + 1, r, L, R, v);
PushUp(u);
}
ll QueryMin(int u, int l, int r, int L, int R) {
if(L <= l && r <= R)
return mi[u];
PushDown(u, l, r);
ll res = LINF;
if(L <= mid) res = min(res, QueryMin(ls, l, mid, L, R));
if(R >= mid + 1) res = min(res, QueryMin(rs, mid + 1, r, L, R));
return res;
}
ll QueryMax(int u, int l, int r, int L, int R) {
if(L <= l && r <= R)
return mx[u];
PushDown(u, l, r);
ll res = -LINF;
if(L <= mid) res = max(res, QueryMax(ls, l, mid, L, R));
if(R >= mid + 1) res = max(res, QueryMax(rs, mid + 1, r, L, R));
return res;
}
ll QuerySum(int u, int l, int r, int L, int R) {
if(L <= l && r <= R)
return sum[u];
PushDown(u, l, r);
ll res = 0;
if(L <= mid) res += QuerySum(ls, l, mid, L, R);
if(R >= mid + 1) res += QuerySum(rs, mid + 1, r, L, R);
return res;
}
#undef ls
#undef rs
#undef mid
} st;
区间设值
struct SegmentTree {
#define ls (u << 1)
#define rs (u << 1 | 1)
#define mid ((l + r) >> 1)
static const int MAXN = 2e5 + 10;
static const ll LINF = 1e18 + 10;
ll tag[MAXN << 2];
ll mi[MAXN << 2];
ll mx[MAXN << 2];
ll sum[MAXN << 2];
void PushUp(int u) {
mi[u] = min(mi[ls], mi[rs]);
mx[u] = max(mx[ls], mx[rs]);
sum[u] = sum[ls] + sum[rs];
}
void PushDown(int u, int l, int r) {
ll t = tag[u];
if(t != LINF) {
tag[ls] = mi[ls] = mx[ls] = t;
sum[ls] = 1LL * (mid - l + 1) * t;
tag[rs] = mi[rs] = mx[rs] = t;
sum[rs] = 1LL * (r - mid) * t;
tag[u] = LINF;
}
}
void Build(int u, int l, int r) {
tag[u] = LINF;
if(l == r) {
mi[u] = mx[u] = sum[u] = 0;
return;
}
Build(ls, l, mid);
Build(rs, mid + 1, r);
PushUp(u);
}
void UpdateSet(int u, int l, int r, int L, int R, ll v) {
if(L <= l && r <= R) {
tag[u] = mi[u] = mx[u] = v;
sum[u] = 1LL * (r - l + 1) * v;
return;
}
PushDown(u, l, r);
if(L <= mid) UpdateSet(ls, l, mid, L, R, v);
if(R >= mid + 1) UpdateSet(rs, mid + 1, r, L, R, v);
PushUp(u);
}
ll QueryMin(int u, int l, int r, int L, int R) {
if(L <= l && r <= R)
return mi[u];
PushDown(u, l, r);
ll res = LINF;
if(L <= mid) res = min(res, QueryMin(ls, l, mid, L, R));
if(R >= mid + 1) res = min(res, QueryMin(rs, mid + 1, r, L, R));
return res;
}
ll QueryMax(int u, int l, int r, int L, int R) {
if(L <= l && r <= R)
return mx[u];
PushDown(u, l, r);
ll res = -LINF;
if(L <= mid) res = max(res, QueryMax(ls, l, mid, L, R));
if(R >= mid + 1) res = max(res, QueryMax(rs, mid + 1, r, L, R));
return res;
}
ll QuerySum(int u, int l, int r, int L, int R) {
if(L <= l && r <= R)
return sum[u];
PushDown(u, l, r);
ll res = 0;
if(L <= mid) res += QuerySum(ls, l, mid, L, R);
if(R >= mid + 1) res += QuerySum(rs, mid + 1, r, L, R);
return res;
}
#undef ls
#undef rs
#undef mid
} st;
混合标记:
加法和乘法的混合标记
超省心版:
struct SegmentTree {
private:
#define ls (u << 1)
#define rs (u << 1 | 1)
#define mid ((l + r) >> 1)
static const int MAXN = 3e5 + 10;
static const ll LINF = 1e18 + 10;
int n;
struct Node {
ll sum, mi, ma;
ll len, tag;
Node() {
sum = 0, mi = 0, ma = 0;
len = 1, tag = 0;
return;
}
Node& operator=(ll val) {
sum = 1LL * len * val, mi = val, ma = val;
tag = 0;
return *this;
}
Node& operator+=(ll val) {
sum += 1LL * len * val, mi += val, ma += val;
tag += val;
return *this;
}
} node[MAXN << 2];
Node merge(const Node &x, const Node &y) {
Node res;
res.sum = x.sum + y.sum;
res.mi = min(x.mi, y.mi);
res.ma = min(x.ma, y.ma);
res.len = x.len + y.len;
res.tag = 0;
return move(res);
}
void pull(int u) {
node[u] = merge(node[ls], node[rs]);
return;
}
void push(int u) {
if (node[u].tag != 0) {
node[ls] += node[u].tag;
node[rs] += node[u].tag;
node[u].tag = 0;
}
return;
}
void iBuild(int u, int l, int r) {
if (l > r)
return;
if (l == r) {
node[u] = Node();
return;
}
iBuild(ls, l, mid);
iBuild(rs, mid + 1, r);
pull(u);
return;
}
void iUpdate(int u, int l, int r, int lpos, int rpos, ll val) {
if (l > r || lpos > r || rpos < l)
return;
if (lpos <= l && r <= rpos) {
node[u] += val;
return;
}
push(u);
iUpdate(ls, l, mid, lpos, rpos, val);
iUpdate(rs, mid + 1, r, lpos, rpos, val);
pull(u);
return;
}
Node iQuery(int u, int l, int r, int lpos, int rpos) {
if (l > r || lpos > r || rpos < l)
return Node();
if (lpos <= l && r <= rpos)
return node[u];
push(u);
Node resL = iQuery(ls, l, mid, lpos, rpos);
Node resR = iQuery(rs, mid + 1, r, lpos, rpos);
return merge(resL, resR);
}
#undef ls
#undef rs
#undef mid
public:
void build(int n) {
this->n = n;
iBuild(1, 1, n);
return;
}
void update(int lpos, int rpos, ll val) {
iUpdate(1, 1, n, lpos, rpos, val);
return;
}
Node query(int lpos, int rpos) {
return iQuery(1, 1, n, lpos, rpos);
}
ll querySum(int lpos, int rpos) {
return query(lpos, rpos).sum;
}
ll queryMin(int lpos, int rpos) {
return query(lpos, rpos).mi;
}
ll queryMax(int lpos, int rpos) {
return query(lpos, rpos).ma;
}
} st;