题目:http://poj.org/problem?id=3468
增加一个更改量数组,施以差值用法则区间修改变为单位置修改;
利用公式可通过树状数组维护两个数组:f与g而直接求出区间和。
代码如下:
#include<iostream> #include<cstdio> using namespace std; long long n,q,a[100005]/*,b[100005],bg[100005]*/,l,r,ad; long long f[100005],g[100005],sum[100005];//f[x]为更改量 char dc; long long query(long long x) { long long k=x; long long summ=0; for(;x;x-=x&-x) summ+=f[x]; long long s2=0; x=k; for(;x;x-=x&-x) s2+=g[x]; return (k+1)*summ-s2; } void add(long long x,long long y)//x单位置增加y { long long k=x; for(x;x<=n;x+=x&-x) f[x]+=y,g[x]+=k*y; } int main() { scanf("%lld%lld",&n,&q); for(long long i=1;i<=n;i++) { scanf("%lld",&sum[i]); sum[i]+=sum[i-1]; // b[i]=a[i]-a[i-1]; // for(int j=i-(i&-i)+1;j<=i;j++)f[i]+=b[j];//差值 // bg[i]=i*b[i]; // for(int j=i-(i&-i)+1;j<=i;j++)g[i]+=bg[j]; // g[i]=i*f[i]; } for(long long i=1;i<=q;i++) { scanf(" %c",&dc); if(dc==‘C‘) { scanf("%lld%lld%lld",&l,&r,&ad); add(l,ad);add(r+1,-ad); } if(dc==‘Q‘) { scanf("%lld%lld",&l,&r); long long ans=query(r)+sum[r]-query(l-1)-sum[l-1]; printf("%lld\n",ans); } } return 0; }