首页 > 代码库 > [模板]洛谷T3372 线段树 模板1

[模板]洛谷T3372 线段树 模板1

变量定义:

sum[]:线段树节点对应区间的元素总和;

addv[]:线段树节点对应区间的所有元素的待追加值(懒标记),初值全部设为0。

 

过程说明:

建树(Build):

若当前节点仅包含原序列中的一个值,即L=R,则直接赋值为序列中该值,否则递归建立左右子树后,将左右子树保存的sum值相加,即得到当前节点的sum值。

 

懒标记下放(Push_down):

将当前节点的addv值下放到左右子树。

细节实现:

1.子树的addv值加上当前节点的addv值;

2.子树的sum值加上(子树包含元素数量*当前节点的addv值);

3.清空当前节点的addv值,即赋值为0。

特别说明:

1.使用前判断,若当前节点的addv值为0则不需执行此下放函数。虽然执行了也不会有影响,但浪费时间。

2.为尽量节省时间,要将判断放在此函数外而不是函数内。

 

区间加(update):

若当前节点完全包含在待更新区间内,则直接修改当前节点的addv值和sum值即可;

否则:

1.若当前节点addv值非0,则进行懒标记下放;

2.若待更新区间与左子树对应区间有交集,则递归更新左子树,同理对右子树也执行类似操作。

3.递归更新子树完成后,重新计算当前节点的sum值。

 

区间查询(query):

若当前节点完全包含在待查询区间内,则直接返回当前节点的sum值;

否则:

1.定义当前节点结果ans=0;

2.若当前节点addv值非0,则进行懒标记下放;

3.若待查询区间与左子树对应区间有交集,则递归查询左子树,并将所得结果加给ans,同理对右子树也执行类似操作。

4.递归查询子树完成后,返回计算好的ans值。

 

代码如下:

 1 #include<cstdio>
 2 #include<iostream>
 3 #include<cstring>
 4 #include<ctime>
 5 #include<cstdlib>
 6 #include<cmath>
 7 #include<algorithm>
 8 #include<string>
 9 #include<stack>
10 #include<queue>
11 #include<vector>
12 #include<map>
13 using namespace std;
14 long long c[2000010];
15 struct sgt{
16     long long sum[2000010];
17     long long addv[2000010];       
18     void build(int o,int l,int r){
19         addv[o]=0;
20         if(l==r)sum[o]=c[l];
21         else{
22             int mid=(l+r)>>1;
23             int lson=o<<1;
24             int rson=lson|1;
25             build(lson,l,mid);
26             build(rson,mid+1,r);
27             sum[o]=sum[lson]+sum[rson];
28         }
29     }
30     void push_down(int o,int l,int r,int mid,int lson,int rson){
31         addv[lson]+=addv[o];
32         addv[rson]+=addv[o];
33         sum[lson]+=(mid-l+1)*addv[o];
34         sum[rson]+=(r-mid)*addv[o];
35         addv[o]=0;
36     }
37     void update(int o,int l,int r,int a,int b,int x){
38         if(l>=a && r<=b){
39             addv[o]+=x;
40             sum[o]+=(r-l+1)*x;
41             return;
42         }
43         else{
44             int mid=(l+r)>>1;
45             int lson=o<<1;
46             int rson=lson|1;
47             if(addv[o])push_down(o,l,r,mid,lson,rson);
48             if(a<=mid)update(lson,l,mid,a,b,x);
49             if(b>mid)update(rson,mid+1,r,a,b,x);
50             sum[o]=sum[lson]+sum[rson];
51         }
52     }
53     long long query(int o,int l,int r,int a,int b){
54         if(l>=a && r<=b)return sum[o];
55         else{
56             int mid=(l+r)>>1;
57             int lson=o<<1;
58             int rson=lson|1;
59             long long ans=0;
60             if(addv[o])push_down(o,l,r,mid,lson,rson);
61             if(a<=mid)ans+=query(lson,l,mid,a,b);
62             if(b>mid)ans+=query(rson,mid+1,r,a,b);
63             return ans;
64         }
65     }
66 };
67 sgt tree;
68 int n,m,i,f;
69 int x,y,k;
70 int main(){
71     scanf("%d%d",&n,&m);
72     for(i=1;i<=n;i++)scanf("%d",&c[i]);
73     tree.build(1,1,n);
74     for(i=1;i<=m;i++){
75         scanf("%d",&f);
76         if(f&1){
77             scanf("%d%d%d",&x,&y,&k);
78             tree.update(1,1,n,x,y,k);
79         }
80         else{
81             scanf("%d%d",&x,&y);
82             printf("%lld\n",tree.query(1,1,n,x,y));
83         }
84     }
85     return 0;
86 }

 

[模板]洛谷T3372 线段树 模板1