题目大意:
一个数列,有两个操作:1.修改操作,将一段区间内的数加上c;2.查询操作,查询一段区间内的数的和。
思路:
线段树裸题,区间修改、区间查询,维护和以及加上的数,由于无序,不需要向下推标记,只需在子树更新完之后更新根节点即可。
代码:
1 #include<cstdio> 2 #include<cstring> 3 #include<iostream> 4 using namespace std; 5 6 long long sum[400001],mor[400001]; 7 8 void up(int cur,int t) 9 { 10 sum[cur]=sum[cur<<1]+sum[cur<<1|1]+t*mor[cur]; 11 } 12 13 void add(int L,int R,int l,int r,int x,int cur) 14 { 15 if (L>=l && R<=r) 16 { 17 mor[cur]+=x; 18 sum[cur]+=(R-L+1)*x; 19 return; 20 } 21 int mid=L+R>>1; 22 if (l<=mid) add(L,mid,l,r,x,cur<<1); 23 if (r>mid) add(mid+1,R,l,r,x,cur<<1|1); 24 up(cur,R-L+1); 25 } 26 27 long long ask(int L,int R,int l,int r,int cur) 28 { 29 if (L>=l && R<=r) return sum[cur]; 30 int mid=L+R>>1; 31 long long ans=mor[cur]*(r-l+1); 32 if (l<=mid) ans+=ask(L,mid,l,min(mid,r),cur<<1); 33 if (r>mid) ans+=ask(mid+1,R,max(l,mid+1),r,cur<<1|1); 34 return ans; 35 } 36 37 int main() 38 { 39 int n,m,i,a,b,c; 40 scanf("%d%d",&n,&m); 41 for (i=1;i<=n;i++) scanf("%d",&a),add(1,n,i,i,a,1); 42 for (i=1;i<=m;i++) 43 { 44 char ch=getchar(); 45 while (ch<‘A‘ || ch>‘Z‘) ch=getchar(); 46 if (ch==‘Q‘) scanf("%d%d",&a,&b),printf("%lld\n",ask(1,n,a,b,1)); 47 else scanf("%d%d%d",&a,&b,&c),add(1,n,a,b,c,1); 48 } 49 return 0; 50 }
时间: 2024-10-25 03:59:48