【模板】线段树区间修改

 2023-09-09 阅读 27 评论 0

摘要:区间修改: 区间修改过程类似于区间询问,例如将[ul, ur]内的所有元素都加上v,则进行如下操作: 当当前区间被区间[ul, ur]所包含时, 优惠区间可以修改吗、  当前的节点值加上区间长度(r - l + 1)乘以v   对当前节点的lazy-tag加上v&

区间修改:

区间修改过程类似于区间询问,例如将[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下传

 

修剪2:未找到多段线复制端点,【代码:】

 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 }

 

模板测试题目传送门

转载于:https://www.cnblogs.com/devilk-sjj/p/9044841.html

版权声明:本站所有资料均为网友推荐收集整理而来,仅供学习和研究交流使用。

原文链接:https://hbdhgg.com/5/21037.html

发表评论:

本站为非赢利网站,部分文章来源或改编自互联网及其他公众平台,主要目的在于分享信息,版权归原作者所有,内容仅供读者参考,如有侵权请联系我们删除!

Copyright © 2022 匯編語言學習筆記 Inc. 保留所有权利。

底部版权信息