思路:我们用b[i]来表示原数组的差分数组,那么给一个区间的每个数加上d,即b[l]+d,b[r+1]-d即可
怎么求一个区间的和呢
$a_1=b_1$
$a_2=b_1+b_2$
$a_3=b_1+b_2+b_3$
.....
$a_x=b_1+b_2+b_3+…+b_x$
假设我们把它补齐成
$a_0=b_1+b_2+b_3+…+b_x$
$a_1=b_1+b_2+b_3+…+b_x$
$a_2=b_1+b_2+b_3+…+b_x$
$a_3=b_1+b_2+b_3+…+b_x$
.....
$a_x=b_1+b_2+b_3+…+b_x$
那么$a_1+a_2+a_3+…a_x=(x+1)*(b_1+b_2+b_3+…+b_x)-b_1-2b_2-3b_3-…-xb_x$
所以我们需要维护b[i]和x*b[i]的前缀和即可
#include<bits/stdc++.h>
using namespace std;
const int N=1e5+5;
typedef long long ll;
int n,m;
ll a[N],tr1[N],tr2[N];
ll lowbit(int x)
{
return x&-x;
}
void add(ll *t,int x,ll k)
{
for(int i=x;i<=n;i+=lowbit(i)) t[i]+=k;
}
ll ask(ll *t,int x)
{
ll res=0;
for(int i=x;i;i-=lowbit(i)) res+=t[i];
return res;
}
int main()
{
scanf("%d %d",&n,&m);
for(int i=1;i<=n;i++)
scanf("%d",&a[i]);
for(int i=1;i<=n;i++)
{
int b=a[i]-a[i-1];
add(tr1,i,b);
add(tr2,i,(ll)i*b);
}
for(int i=1;i<=m;i++)
{
char c;
int l,r,d;
scanf(" %c%d%d",&c,&l,&r);
if(c=='C')
{
scanf("%d",&d);
add(tr1,l,d);
add(tr2,l,(ll)l*d);
add(tr1,r+1,-d);
add(tr2,r+1,(ll)(r+1)*(-d));
}
else
{
printf("%lld\n",(ll)(r+1)*ask(tr1,r)-ask(tr2,r)-((ll)l*ask(tr1,l-1)-ask(tr2,l-1)));
}
}
return 0;
}