区间查询,区间修改

 1 #include <iostream>
 2 #include <cstdio>
 3 #include <algorithm>
 4 #include <cstring>
 5 using namespace std;
 6 typedef long long ll;
 7 
 8 const int N=2e5+5;
 9 int n,m;
10 ll lazy[N<<2],sum[N<<2];
11 
12 void PushUp(int rt){
13     sum[rt]=sum[rt<<1]+sum[rt<<1|1];
14 }
15 
16 void PushDown(int rt,int l,int r){
17     if(lazy[rt]){
18         lazy[rt<<1]+=lazy[rt];  //lazy标记往下传
19         lazy[rt<<1|1]+=lazy[rt];
20         ll mid=(l+r)>>1;
21         sum[rt<<1]+=(mid-l+1)*lazy[rt];
22         sum[rt<<1|1]+=(r-mid)*lazy[rt];
23         lazy[rt]=0;   //防止重复修改,往下传后清零
24     }
25 }
26 
27 void Build(int l,int r,int rt){
28     if(l==r) {scanf("%d",&sum[rt]);return;}
29     ll mid=(l+r)>>1;
30     if(l<=mid) Build(l,mid,rt<<1);
31     if(r>mid) Build(mid+1,r,rt<<1|1);
32     PushUp(rt);  //底层往上回溯
33 }
34 
35 void Add(int l,int r,int rt,int L,int R,int V){
36     if(L<=l&&R>=r){
37         sum[rt]+=(r-l+1)*V;
38         lazy[rt]+=V;
39         return;
40     }
41     PushDown(rt,l,r); //下面的代码要用到左儿子,有儿子,懒惰 标记要往下传
42     int mid=(l+r)>>1;
43     if(L<=mid) Add(l,mid,rt<<1,L,R,V);
44     if(R>mid) Add(mid+1,r,rt<<1|1,L,R,V);
45     PushUp(rt);  //不要忘记往上更新
46 }
47 
48 ll query(int l,int r,int rt,int L,int R){
49     if(L<=l&&R>=r){
50         return sum[rt];
51     }
52     PushDown(rt,l,r); //要往下用就得往下更新
53     ll mid=(l+r)>>1,sum=0;
54     if(L<=mid) sum+=query(l,mid,rt<<1,L,R);
55     if(R>mid) sum+=query(mid+1,r,rt<<1|1,L,R);
56     return sum;
57 }
58 
59 int main()
60 {
61     scanf("%d",&n);
62     Build(1,n,1);
63     scanf("%d",&m);
64     for(int i=1;i<=m;i++){
65         int a,b,c,X;
66         scanf("%d",&a);
67         if(a==1){
68             scanf("%d%d%d",&b,&c,&X);
69             Add(1,n,1,b,c,X);
70         }
71         else if(a==2){
72             scanf("%d%d",&b,&c);
73             printf("%lld
",query(1,n,1,b,c));
74         }
75     }
76     return 0;
77 }
View Code
原文地址:https://www.cnblogs.com/qq-1585047819/p/10987799.html