模板线段树区间修改
Posted DEVILK
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了模板线段树区间修改相关的知识,希望对你有一定的参考价值。
区间修改:
区间修改过程类似于区间询问,例如将[ul, ur]内的所有元素都加上v,则进行如下操作:
当当前区间被区间[ul, ur]所包含时,
当前的节点值加上区间长度(r - l + 1)乘以v
对当前节点的lazy-tag加上v,修改结束
否则,将当前节点的lazy-tag下传,分别修改左孩子和右孩子(一定条件下),然后更新此节点的值
lazy-tag下传:
如果当前节点没有lazy-tag,直接return
否则:1. 将左孩子右孩子分别加上lazy-tag * 区间长度的值
2. 左孩子和右孩子的懒惰标记加上lazy-tag
3. 当前节点的lazy-tag清零
注意区间询问的时候也要lazy-tag下传
【代码:】
1 //线段树区间修改 2 #include<iostream> 3 #include<cstdio> 4 using namespace std; 5 6 const int MAXN = 100000 + 1; 7 8 int n, m, a[MAXN]; 9 struct Segment { 10 long long sum, lazy; 11 Segment() { 12 sum = lazy = 0; 13 } 14 }t[MAXN << 2]; 15 16 void Build(int o, int l, int r) { 17 if(l == r) t[o].sum = a[l]; 18 else { 19 int mid = (l + r) >> 1; 20 Build(o << 1, l, mid); 21 Build(o << 1|1, mid + 1, r); 22 t[o].sum = t[o << 1].sum + t[o << 1|1].sum; 23 } 24 } 25 void down(int o, int len) { 26 if(!t[o].lazy) return; 27 t[o << 1].sum += t[o].lazy * (len - (len >> 1)); 28 t[o << 1|1].sum += t[o].lazy * (len >> 1); 29 t[o << 1].lazy += t[o].lazy; 30 t[o << 1|1].lazy += t[o].lazy; 31 t[o].lazy = 0; 32 } 33 void Update(int o, int l, int r, int ul, int ur, int v) { 34 if(ul <= l && r <= ur) { 35 t[o].sum += (r - l + 1) * v; 36 t[o].lazy += v; 37 } 38 else { 39 down(o, r - l + 1); 40 int mid = (l + r) >> 1; 41 if(ul <= mid) Update(o << 1, l, mid, ul, ur, v); 42 if(ur > mid) Update(o << 1|1, mid + 1, r, ul, ur, v); 43 t[o].sum = t[o << 1].sum + t[o << 1|1].sum; 44 } 45 } 46 long long Query(int o, int l, int r, int ql, int qr) { 47 if(ql <= l && r <= qr) { 48 return t[o].sum; 49 } 50 int mid = (l + r) >> 1; 51 long long ret = 0; 52 down(o, r - l + 1); 53 if(ql <= mid) ret += Query(o << 1, l, mid, ql, qr); 54 if(qr > mid) ret += Query(o << 1|1, mid + 1, r, ql, qr); 55 return ret; 56 } 57 int main() { 58 scanf("%d%d", &n, &m); 59 for(int i = 1; i <= n; ++i) 60 scanf("%d", &a[i]); 61 Build(1, 1, n); 62 while(m--) { 63 int fl, x, y; 64 scanf("%d%d%d", &fl, &x, &y); 65 if(fl == 1) { 66 int k; 67 scanf("%d", &k); 68 Update(1, 1, n, x, y, k); 69 } 70 else printf("%lld\n", Query(1, 1, n, x, y)); 71 } 72 }
以上是关于模板线段树区间修改的主要内容,如果未能解决你的问题,请参考以下文章