线段树的区间修改

  1 #include <iostream>
  2 #include<stdio.h>
  3 # define LC (p<<1)  //该节点的左孩子
  4 # define RC (p<<1|1)//右孩子
  5 using namespace std;
  6 
  7 //很类似与树状数组
  8 int n,m;
  9 struct Segment_Tree
 10 {
 11     int sum;
 12     int lazy;//懒标记
 13 }tree[1000000];   //线段树数组
 14 int  a[1000000];
 15 void build_tree(int p,int l,int r)  //p当前节点,l,r,表示范围
 16 {
 17     if(l==r) //递归的出口
 18     {
 19         tree[p].sum=a[l];  //就是赋予叶子节点的值
 20     }
 21    else
 22    {
 23         int mid=(r+l)/2;//左右分开建树
 24     build_tree(LC,l,mid);
 25     build_tree(RC,mid+1,r);
 26 tree[p].sum=tree[LC].sum+tree[RC].sum;//左右孩子节点的值相加就是父节点的值
 27    }
 28 
 29 }
 30 void free(int p,int l,int r,int k)
 31 {
 32    tree[p].lazy+=k; 
 33    tree[p].sum+=k*(r-l+1);//将当前节点假装覆盖想要的值,这个值是你想在这个区间进行修改的值的和
 34     return;
 35 }
 36 void pushdown(int p,int l,int r)
 37 {
 38     int mid=(r+l)/2;
 39     free(LC,l,mid,tree[p].lazy);
 40     free(RC,mid+1,r,tree[p].lazy);
 41     tree[p].lazy=0;//两个孩子有了假想覆盖值之后需要消去父节点的覆盖值
 42     return;
 43 }
 44 void update(int L,int R,int p,int l,int r,int k)
 45 {
 46 
 47      int mid=(r+l)/2;
 48      if(l>=L&&r<=R)  //维护区间刚好在修改区间的里面,就优先把维护区间覆盖
 49      {
 50          free(p,l,r,k);
 51          return ;
 52      }
 53     else
 54     {
 55          if(L<=mid)
 56      {
 57          update(L,R,LC,l,mid,k);
 58      }
 59      if(R>mid)
 60      {
 61          update(L,R,RC,mid+1,r,k);
 62      }
 63 
 64     }
 65      tree[p].sum=tree[LC].sum+tree[RC].sum;//节点值的修改使得这个sum需要一直修改
 66      return ;
 67 }
 68 int query(int L,int R,int p,int l,int r) //区间查询
 69 {
 70     int res=0;
 71     if(l>=L&&r<=R)
 72     {
 73         return tree[p].sum;
 74     }
 75 
 76 
 77     pushdown(p,l,r);
 78 
 79     int mid=(r+l)/2;
 80     if(L<=mid)
 81     {
 82         res+=query(L,R,LC,l,mid);
 83     }
 84    if(R>mid)
 85     {
 86         res+=query(L,R,RC,mid+1,r);
 87     }
 88     return res;
 89 }
 90 int main()
 91 {
 92     int x,y,c,k;
 93     scanf("%d%d",&n,&m);
 94     register int i;
 95     for(i=1;i<=n;i++){
 96         scanf("%d",&a[i]);
 97     }
 98     build_tree(1,1,n);
 99     for(i=1;i<=m;i++){
100         scanf("%d",&c);
101         if(c==1){
102             scanf("%d%d%d",&x,&y,&k);
103             update(x,y,1,1,n,k);
104         }else{
105             scanf("%d%d",&x,&y);
106             printf("%d\n",query(x,y,1,1,n));
107         }
108     }
109     return 0;
110 }

 

posted @ 2022-02-09 20:45  九点的日落  阅读(265)  评论(0)    收藏  举报