模板线段树区间修改

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 }

 

模板测试题目传送门

以上是关于模板线段树区间修改的主要内容,如果未能解决你的问题,请参考以下文章

模板线段树(区间加)

模板线段树区间修改

线段树区间修改 P3372 模板线段树 1

线段树区间修改和查询和单点查询(线段树模板1)

「模板」线段树静态开点(单点+区间修改)动态开点

模板 线段树的区间修改