给出了一个序列,你需要处理如下两种询问。
"C a b c"表示给[a, b]区间中的值全部增加c (-10000 ≤ c ≤ 10000)。
"Q a b" 询问[a, b]区间中所有值的和。
第一行包含两个整数N, Q。1 ≤ N,Q ≤ 100000.
第二行包含n个整数,表示初始的序列A (-1000000000 ≤ Ai ≤ 1000000000)。
接下来Q行询问,格式如题目描述。
Sample Input
10 5 1 2 3 4 5 6 7 8 9 10 Q 4 4 Q 1 10 Q 2 4 C 3 6 3 Q 2 4
Sample Output
4 55 9 15
这道题也比较简单,成段更新
体现了线段树的好处
不过要注意这里增加了两个方法 pushdown和pushup
pushup就是向上更新,也就是说父节点的和是两个子节点的和相加 从叶子节点累加上去到了根节点的话,最终根节点的和就是所有叶子节点的值加起来
有点像BOSS拿的钱就是各个小弟拿的钱加起来 就那么个意思~
pushdown就是向下更新,也就是说 比如你输入了 C 1 4 1也就是在第1个数到第4个数全部加1
首先你就要找到1 到4 然后在1到4 下面的1 到 2 和 3 到 4 把要加的数也就是1 加上去 依次类推在 1 到 2 下面的1 和 2 加上1
那么结果就是你在 1 2 3 4这四个叶子节点中的值都加了1,在这里有两个要维护的域 一个是“加多少” tree[i].add ,另外一个是“加了之后是多少” tree[i].sum
在update中的
if(A<=l&&B>=r) { tree[i].add+=C; tree[i].sum+=C*(r-l+1); return ; }r-l+1是这段区间的长度也就是线段长度,比如上面所说的例子如果恰好是1 到 4 的话直接可以在 1 到4线段中加上 1*4=4 此次update就完成了
说到这里已经很清楚了,下面上代码:
#include<cstdio> #define N 100005 int n,m; long long num[N]; struct node { int l,r; long long sum; long long add; } tree[N<<2]; void pushup(int i) { tree[i].sum=tree[i<<1].sum+tree[i<<1|1].sum; } void build(int l,int r,int i) { tree[i].l=l; tree[i].r=r; if(l==r) { tree[i].sum=num[l]; return ; } int mid=(l+r)>>1; build(l,mid,i<<1); build(mid+1,r,i<<1|1); pushup(i); } void pushdown(int rt,int dis) { if(tree[rt].add) { tree[rt<<1].add+=tree[rt].add; tree[rt<<1|1].add+=tree[rt].add; tree[rt<<1].sum+=tree[rt].add*(dis-(dis>>1)); tree[rt<<1|1].sum+=tree[rt].add*(dis>>1); tree[rt].add=0; } } void update(int A,int B,int C ,int l,int r,int i) { if(A<=l&&B>=r) { tree[i].add+=C; tree[i].sum+=C*(r-l+1); return ; } pushdown(i,r-l+1); int mid=(l+r)>>1; if(A<=mid)update(A,B,C,l,mid,i<<1); if(B>mid)update(A,B,C,mid+1,r,i<<1|1); pushup(i); } long long query(int A,int B,int l,int r,int i) { if(A<=l&&B>=r) { return tree[i].sum; } pushdown(i,r-l+1); long long ans=0; int mid=(l+r)>>1; if(A<=mid) ans+=query(A,B,l,mid,i<<1); if(B>mid) ans+=query(A,B,mid+1,r,i<<1|1); return ans; } int main() { scanf("%d%d",&n,&m); for(int i=1; i<=n; i++) scanf("%I64d",&num[i]); build(1,n,1); while(m--) { char s[6]; int a,b,c; scanf("%s",&s); if(s[0]=='C') { scanf("%d%d%d",&a,&b,&c); update(a,b,c,1,n,1); } else { scanf("%d%d",&a,&b); printf("%I64d\n",query(a,b,1,n,1)); } } return 0; }