区间修改有别于单点修改,如果每次都修改到叶子节点,复杂度可以退化到O(n)。
因此为节点引入一个lazy标记,修改时,如果待修改区间与某个节点的区间重合,那么这个节点更新值后标记lazy,不再修改其子节点。
类似于查询操作,这个修改操作的复杂度是O(logn)。
另外,查询或修改时,如果遇到已经标记了lazy的节点,需要先将lazy标记下放到两个子节点,再进行后续处理。
#include <stdio.h> #include <algorithm> typedef struct _seg_tree_ { int left, right; int val; bool lazy_tag; _seg_tree_ *lson = NULL, *rson = NULL; _seg_tree_(int left_idx, int right_idx, int value) : left(left_idx), right(right_idx), val(value), lazy_tag(false) {} } seg_tree, *pseg_tree; pseg_tree construct_seg_tree(int left, int right) { if (left == right) { int val; scanf("%d", &val); return new seg_tree(left, left, val); } int mid = left + (right - left) / 2; pseg_tree lson = construct_seg_tree(left, mid); pseg_tree rson = construct_seg_tree(mid + 1, right); int val = lson->val + rson->val; pseg_tree ans = new seg_tree(left, right, val); ans->lson = lson; ans->rson = rson; return ans; } void lazy_down(pseg_tree proot) { int mid = proot->left + (proot->right - proot->left) / 2; proot->lazy_tag = false; int x = proot->val / (proot->right - proot->left + 1); proot->lson->lazy_tag = true; proot->lson->val = x * (mid - proot->lson->left + 1); proot->rson->lazy_tag = true; proot->rson->val = x * (proot->rson->right - mid); } int query_seg_tree(pseg_tree proot, int left, int right) { if (left == proot->left && right == proot->right) { return proot->val; } int mid = proot->left + (proot->right - proot->left) / 2; if (proot->lazy_tag == true) { lazy_down(proot); } if (left > mid) { return query_seg_tree(proot->rson, left, right); } if (right <= mid) { return query_seg_tree(proot->lson, left, right); } return query_seg_tree(proot->lson, left, mid) + query_seg_tree(proot->rson, mid + 1, right); } void modify_seg_tree(pseg_tree proot, int left, int right, int val) { if (left == proot->left && right == proot->right) { proot->val = val * (right - left + 1); proot->lazy_tag = true; return; } int mid = proot->left + (proot->right - proot->left) / 2; if (proot->lazy_tag == true) { lazy_down(proot); } if (left > mid) { modify_seg_tree(proot->rson, left, right, val); } else if (right <= mid) { modify_seg_tree(proot->lson, left, right, val); } else { modify_seg_tree(proot->rson, mid + 1, right, val); modify_seg_tree(proot->lson, left, mid, val); } proot->val = proot->lson->val + proot->rson->val; } int main(){ int n, q; scanf("%d", &n); pseg_tree proot = construct_seg_tree(1, n); scanf("%d", &q); int op, left, right, value; while (q--) { scanf("%d%d%d", &op, &left, &right); if (op == 0) { int ans = query_seg_tree(proot, left, right); printf("%d\n", ans); } else { scanf("%d", &value); modify_seg_tree(proot, left, right, value); } } return 0; }
时间: 2024-11-09 23:15:54