首先还是先利用区间修改 单点查询用过的差分思想(将区间的修改操作变成单点的修改),我们先搞一个c数组作为差分数组
a数组是原数组,c数组是差分数组。
简单可证:
即 a[1] = c[1] , a[2] = c[2] + c[1], a[3] = c[3] + c[2] + c[1],……;
那么可以得到以下式子:
a[1]+a[2]+...+a[i]
=c[1] + ( c[1] + c[2] ) + ... + ( c[1] + c[2] + ... + c[i] )
=i*c[1]+(i-1)*c[2]+...+c[i]
=i *(c[1]+c[2]+...+c[i])-1*c[2]-...-(i-1)*c[i]
于是,我们再搞一个数组d=(i-1)*c[i]
那之前的式子就可以表示为
a[1]+a[2]+…+a[i]=i*(c[1]+c[2]+...+c[i])-(d[1]+d[2]+...+d[i]);
#include<iostream> #include<cstdio> using namespace std; long long n,m; long long a[500009]; long long c[500009],d[500009]; long long lowbit(long long x) { return (x&(-x)); } void change(long long *e,long long x,long long k) { for(int i=x;i<=n;i+=lowbit(i)) { e[i]+=k; } } long long query(long long *e,long long x) { long long sum=0; for(int i=x;i>=1;i-=lowbit(i)) { sum+=e[i]; } return sum; } inline long long read() { long long x=0,f=1;char ch=getchar(); while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();} while(ch>='0'&&ch<='9'){x=(x<<1)+(x<<3)+(ch^48);ch=getchar();} return x*f; } int main() { n=read(),m=read(); for(int i=1;i<=n;i++) { a[i]=read(); change(c,i,a[i]-a[i-1]); change(d,i,(long long)(i-1)*(a[i]-a[i-1])); } for(int i=1;i<=m;i++) { long long p; cin>>p; if(p==1)//修改 { long long r,l,v; cin>>l>>r>>v; change(c,l,v); change(c,r+1,-v); change(d,l,(long long)(l-1)*v); change(d,r+1,(long long)-r*v); } if(p==2)//统计 { long long r,l; cin>>l>>r; long long t1=query(c,l-1)*(l-1)-query(d,l-1); long long t2=query(c,r)*r-query(d,r); printf("%lld ",t2-t1); } } return 0; } /* 5 2 1 7 6 5 8 1 2 3 1//修改【2~3】+1 2 2 4//查询2~4 */