单点修改
struct SegmentTree {
#define ls (u << 1)
#define rs (u << 1 | 1)
#define mid ((l + r) >> 1)
static const int MAXN = 5e5 + 10;
static const ll LINF = 1e18 + 10;
int n;
ll sum[MAXN << 2];
void iBuild(int u, int l, int r) {
if (l > r) { return; }
if (l == r) { sum[u] = a[l];}
else {
iBuild(ls, l, mid);
iBuild(rs, mid + 1, r);
sum[u] = sum[ls] + sum[rs];
}
}
void iAdd(int u, int l, int r, int pos, ll val) {
if (l > r || pos < l || pos > r) { return; }
if (l == r) { sum[u] += val; }
else {
iAdd(ls, l, mid, pos, val);
iAdd(rs, mid + 1, r, pos, val);
sum[u] = sum[ls] + sum[rs];
}
}
ll iSum(int u, int l, int r, int L, int R) {
ll res = 0;
if (l > r || L > R || L > r || R < l) { return res; }
if (L <= l && r <= R) { res = sum[u]; }
else {
res += iSum(ls, l, mid, L, R);
res += iSum(rs, mid + 1, r, L, R);
}
return res;
}
#undef ls
#undef rs
#undef mid
} tree;
完整功能模板代码
struct SegmentTree {
private:
#define ls (u << 1)
#define rs (u << 1 | 1)
#define mid ((l + r) >> 1)
static const int MAXN = 5e5 + 10;
static const ll LINF = 1e18 + 10;
int n;
int *a1;
ll *a2;
struct Node {
int l, r;
ll sum;
ll mi;
ll ma;
Node() {
l = -1, r = -1,
sum = 0;
mi = LINF;
ma = -LINF;
}
Node &operator=(ll val) {
sum = val;
mi = val;
ma = val;
return *this;
}
Node &operator+=(ll val) {
sum += val;
mi += val;
ma += val;
return *this;
}
void show() {
printf(" [%d, %d] sum=%lld mi=%lld ma=%lld
", l, r, sum, mi, ma);
}
} node[MAXN << 2];
Node mergeFrom(const Node &x, const Node &y) {
if (x.l == -1 && x.r == -1)
return y;
if (y.l == -1 && y.r == -1)
return x;
Node res;
res.l = x.l, res.r = y.r;
res.sum = x.sum + y.sum;
res.mi = min(x.mi, y.mi);
res.ma = min(x.ma, y.ma);
return move(res);
}
void iBuild(int u, int l, int r) {
if (l > r) { return; }
if (l == r) {
node[u] = Node();
node[u].l = l;
node[u].r = l;
if (a1 != nullptr)
node[u] = a1[l];
if (a2 != nullptr)
node[u] = a2[l];
} else {
iBuild(ls, l, mid);
iBuild(rs, mid + 1, r);
node[u] = mergeFrom(node[ls], node[rs]);
}
}
void iSet(int u, int l, int r, int pos, ll val) {
if (l > r || pos < l || pos > r) { return; }
if (l == r) { node[u] = val; }
else {
if (pos <= mid) { iSet(ls, l, mid, pos, val); }
if (pos >= mid + 1) { iSet(rs, mid + 1, r, pos, val); }
node[u] = mergeFrom(node[ls], node[rs]);
}
}
void iAdd(int u, int l, int r, int pos, ll val) {
if (l > r || pos < l || pos > r) { return; }
if (l == r) { node[u] += val; }
else {
if (pos <= mid) { iAdd(ls, l, mid, pos, val); }
if (pos >= mid + 1) { iAdd(rs, mid + 1, r, pos, val); }
node[u] = mergeFrom(node[ls], node[rs]);
}
}
Node iQuery(int u, int l, int r, int L, int R) {
Node res;
if (l > r || L > R || L > r || R < l) { return res; }
if (L <= l && r <= R) { res = node[u]; }
else {
if (L <= mid) { res = mergeFrom(iQuery(ls, l, mid, L, R), res); }
if (R >= mid + 1) { res = mergeFrom(res, iQuery(rs, mid + 1, r, L, R)); }
}
return res;
}
#undef ls
#undef rs
#undef mid
public:
void Build(int n) {
this->n = n, this->a1 = nullptr, this->a2 = nullptr;
iBuild(1, 1, n);
}
void Build(int n, int *a) {
this->n = n, this->a1 = a, this->a2 = nullptr;
iBuild(1, 1, n);
}
void Build(int n, ll *a) {
this->n = n, this->a1 = nullptr, this->a2 = a;
iBuild(1, 1, n);
}
void Set(int pos, ll val) {
// printf("Set %d, %lld
", pos, val);
iSet(1, 1, n, pos, val);
}
void Add(int pos, ll val) {
// printf("Add %d, %lld
", pos, val);
iAdd(1, 1, n, pos, val);
}
Node Query(int L, int R) {
// printf("Query [%d, %d]
", L, R);
return iQuery(1, 1, n, L, R);
}
ll Sum(int L, int R) { return Query(L, R).sum; }
ll Min(int L, int R) { return Query(L, R).mi; }
ll Max(int L, int R) { return Query(L, R).ma; }
} tree;
验证链接:https://www.luogu.com.cn/problem/P3374
区间修改
struct SegmentTree {
#define ls (u << 1)
#define rs (u << 1 | 1)
#define mid ((l + r) >> 1)
static const int MAXN = 1e5 + 10;
static const ll LINF = 1e18 + 10;
int n;
ll tag[MAXN << 2];
ll sum[MAXN << 2];
void pushUp(int u) {
sum[u] = sum[ls] + sum[rs];
}
void pushDown(int u, int l, int r) {
ll t = tag[u];
if (t != 0) {
tag[ls] += t;
sum[ls] += 1LL * (mid - l + 1) * t;
tag[rs] += t;
sum[rs] += 1LL * (r - mid) * t;
tag[u] = 0;
}
}
void iBuild(int u, int l, int r) {
if (l > r) { return; }
tag[u] = 0;
if (l == r) { sum[u] = a[l];}
else {
iBuild(ls, l, mid);
iBuild(rs, mid + 1, r);
pushUp(u);
}
}
void iAdd(int u, int l, int r, int L, int R, ll val) {
if (l > r || L > R || L > r || R < l) { return; }
if (L <= l && r <= R) {
tag[u] += val;
sum[u] += 1LL * (r - l + 1) * val;
} else {
pushDown(u, l, r);
iAdd(ls, l, mid, L, R, val);
iAdd(rs, mid + 1, r, L, R, val);
pushUp(u);
}
}
ll iSum(int u, int l, int r, int L, int R) {
ll res = 0;
if (l > r || L > R || L > r || R < l) { return res; }
if (L <= l && r <= R) { res = sum[u]; }
else {
pushDown(u, l, r);
res += iSum(ls, l, mid, L, R);
res += iSum(rs, mid + 1, r, L, R);
}
return res;
}
#undef ls
#undef rs
#undef mid
} tree;
单点修改 字符串哈希
用来维护字符串哈希时,需要注意的是额外维护真实的左区间的长度。