线段树模板

线段树模板

/* 线段树 */
#include <array>
#include <bits/stdc++.h>
using namespace std;

// 预处理
// #define lc p=p*2
#define lc (p << 1)
// #define rc p=p*2+1
#define rc (p << 1 | 1)
#define N  100005
#define LL long long

array< LL, N > arr;
struct node {
    LL l, r, sum, tag;
};

array< node, N * 4 > tree;

// 建树
// p 当前节点 ;[l,r] 当前区间
void build(LL p, LL l, LL r) {
    tree[p] = {l, r, arr[l], 0};
    // 已经来到叶子节点了
    if (l == r) {
        // cout<<p<<":
        // ["<<tree[p].l<<","<<tree[p].r<<"]-->"<<tree[p].sum<<endl;
        return;
    }
    LL mid = (l + r) >> 1;  // 分治
    build(lc, l, mid);      // 左子树
    build(rc, mid + 1, r);  // 右子树
    tree[p].sum = tree[lc].sum + tree[rc].sum;
    // cout<<p<<":
    // ["<<tree[p].l<<","<<tree[p].r<<"]-->"<<tree[p].sum<<endl;
}

// 单点修改
void update(LL p, LL x, LL k) {
    // 到达叶子节点,且到达目标节点x
    if (tree[p].l == x && tree[p].r == x) {
        tree[p].sum += k;
        return;
    }
    LL mid = (tree[p].l + tree[p].r) >> 1;
    if (x <= mid) {
        update(lc, x, k);  // 左子树
    }
    if (x > mid) {
        update(rc, x, k);  // 右子树
    }
    tree[p].sum = tree[lc].sum + tree[rc].sum;
}

// 向下更新
void pushdown(LL p) {
    if (tree[p].tag != 0) {
        tree[lc].sum +=
            tree[p].tag * (tree[lc].r - tree[lc].l + 1);
        tree[rc].sum +=
            tree[p].tag * (tree[rc].r - tree[rc].l + 1);
        tree[lc].tag += tree[p].tag;
        tree[rc].tag += tree[p].tag;
        tree[p].tag = 0;
    }
}

// 向上更新
void pushup(LL p) {
    tree[p].sum = tree[lc].sum + tree[rc].sum;
}

// 区间修改
void update(LL p, LL l, LL r, LL k) {
    if (l <= tree[p].l && tree[p].r <= r) {
        tree[p].sum += (tree[p].r - tree[p].l + 1) * k;
        tree[p].tag += k;
        return;
    }
    LL m = (tree[p].l + tree[p].r) >> 1;
    pushdown(p);
    if (l <= m) {
        update(lc, l, r, k);
    }
    if (r > m) {
        update(rc, l, r, k);
    }
    pushup(p);
}

// 区间查询
LL query(LL p, LL x, LL y) {
    // 查询区间完全覆盖该区间,则返回
    if (x <= tree[p].l && tree[p].r <= y) {
        return tree[p].sum;
    }
    LL mid = (tree[p].l + tree[p].r) >> 1;  // 分治
    pushdown(p);
    LL sum = 0;
    if (x <= mid) {
        sum += query(lc, x, y);
    }
    if (y > mid) {
        sum += query(rc, x, y);
    }
    return sum;
}

LL n;
LL m;

int main() {
    cin >> n >> m;
    for (LL i = 1; i <= n; i++) {
        cin >> arr[i];
    }

    build(1, 1, n);
    while (m-- != 0) {
        LL option;
        LL x;
        LL y;
        LL k;
        cin >> option >> x >> y;
        if (option == 2) {
            cout << query(1, x, y) << endl;
        } else {
            cin >> k;
            update(1, x, y, k);
        }
    }
    return 0;
}
posted on 2025-02-16 12:55  EasonLikeMath  阅读(3)  评论(0)    收藏  举报