15
这道题是对一个区间中所有点进行更新,然后求区间和。
#include<stdio.h> #include<iostream> #include<string.h> #define MAXN 100000+10 using namespace std; long long initsum[MAXN]; long long c1[MAXN],c2[MAXN]; int n; int lowbit(int x)///利用计算机补码计算2^k(其中k为x二进制末尾0的个数) { return x&(-x); } void add(long long *c,int i,int val)///修改操作,更新C[i],如果A[i]发生改变,那么C[i]节点发生改变,C[i]的祖先也发生改变。 { while(i<=n) { c[i]+=val; i+=lowbit(i); } } int sum(long long *c,int i)///计算前i项的和 { int s=0; while(i>0) { s+=c[i]; i-=lowbit(i); } return s; } int main() { int m,a,b,e,t; long long ans; char str[2]; while(~scanf("%d%d",&n,&m)) { memset(c1,0,sizeof(c1)); memset(c2,0,sizeof(c2)); memset(initsum, 0, sizeof (initsum)); for(int i=1; i<=n; i++) { scanf("%d",&t); initsum[i] = initsum[i-1] + t; } while(m--) { scanf("%s",str); if(str[0]=='Q') { scanf("%d%d",&a,&b); ans=initsum[b]-initsum[a-1]; ans+=(b+1)*sum(c1,b)-sum(c2,b); ans-=(a*sum(c1,a-1)-sum(c2,a-1)); printf("%lld\n",ans); } else { scanf("%d%d%d",&a,&b,&e); add(c1,a,e); add(c2,a,a*e);///这两个add后,区间c[a...n]每个数都增加了c。 add(c1,b+1,-e); add(c2,b+1,-(b+1)*e); ///这两个update后,区间c[b+1...n]每个数都减少了c } } } }