【算法

单点修改

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;

单点修改 字符串哈希

用来维护字符串哈希时,需要注意的是额外维护真实的左区间的长度。

原文地址:https://www.cnblogs.com/purinliang/p/13665942.html