C++ 线段树代码示例:区间求和与修改
以下是一份简单的线段树代码,实现区间求和和区间修改:
const int MAXN = 1e5 + 5;
int n, q;
int a[MAXN];
int tree[MAXN << 2], lazy[MAXN << 2];
void build(int node, int left, int right) {
if (left == right) {
tree[node] = a[left];
return;
}
int mid = (left + right) >> 1;
build(node << 1, left, mid);
build(node << 1 | 1, mid + 1, right);
tree[node] = tree[node << 1] + tree[node << 1 | 1];
}
void pushdown(int node, int left, int right) {
if (lazy[node]) {
int mid = (left + right) >> 1;
tree[node << 1] += lazy[node] * (mid - left + 1);
tree[node << 1 | 1] += lazy[node] * (right - mid);
lazy[node << 1] += lazy[node];
lazy[node << 1 | 1] += lazy[node];
lazy[node] = 0;
}
}
void update(int node, int left, int right, int l, int r, int val) {
if (left > r || right < l) return;
if (left >= l && right <= r) {
tree[node] += val * (right - left + 1);
lazy[node] += val;
return;
}
pushdown(node, left, right);
int mid = (left + right) >> 1;
update(node << 1, left, mid, l, r, val);
update(node << 1 | 1, mid + 1, right, l, r, val);
tree[node] = tree[node << 1] + tree[node << 1 | 1];
}
int query(int node, int left, int right, int l, int r) {
if (left > r || right < l) return 0;
if (left >= l && right <= r) return tree[node];
pushdown(node, left, right);
int mid = (left + right) >> 1;
return query(node << 1, left, mid, l, r) + query(node << 1 | 1, mid + 1, right, l, r);
}
int main() {
scanf("%d%d", &n, &q);
for (int i = 1; i <= n; ++i) {
scanf("%d", &a[i]);
}
build(1, 1, n);
while (q--) {
int op, l, r, val;
scanf("%d%d%d", &op, &l, &r);
if (op == 1) {
scanf("%d", &val);
update(1, 1, n, l, r, val);
} else {
printf("%d\n", query(1, 1, n, l, r));
}
}
return 0;
}
其中 tree 数组表示线段树的节点值,lazy 数组表示懒标记。build 函数用于建树,update 函数用于区间修改,query 函数用于区间查询。在 update 函数中,先判断当前节点是否需要下传懒标记,然后递归修改左右子树,并更新当前节点的值。在 query 函数中同样需要先判断当前节点是否需要下传懒标记,然后递归查询左右子树并返回结果。
原文地址: http://www.cveoy.top/t/topic/jCpS 著作权归作者所有。请勿转载和采集!