• [模板]洛谷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
    ",tree.query(1,1,n,x,y));
    83         }
    84     }
    85     return 0;
    86 }
  • 相关阅读:
    学习java随笔第二篇:java开发工具——Eclipse
    GDB
    【转】图像分割(Image Segmentation)
    [转]C#Windows窗体打开图像与保存
    【转】opencv 分水岭算法cvWatershed
    C#中Rectangle(Point, Size) 和Rectangle(Int32, Int32, Int32, Int32) 区别
    【转】数组和图像的转换
    .Net的垃圾回收机制(GC)之拙见——托管类型的垃圾回收
    【动态规划】滚动数组的求解(C++)
    C#编程语言之委托与事件(二)—— C#事件
  • 原文地址:https://www.cnblogs.com/running-coder-wfh/p/6901456.html
Copyright © 2020-2023  润新知