本题关键在于差分的前缀和是原始数据
而求区间和还需要再次求前缀和
两波前缀和可以合并成一波
合并之后会发现前面每项加的次数和从哪查询还有关
所以再次转化成总的减去i * b[i]
i * b[i]就可以用树状数组来维护了
#include<algorithm>
#include<cstdio>
#include<iostream>
using namespace std;
const int N=1e5+5,inf=0x3f3f3f3f;
typedef long long ll;
int n,m;
ll a[N],c[2][N];
ll ask(int x,int k)
{
ll res=0;
for(;x;x-=x&-x)res+=c[k][x];
return res;
}
void add(int x,int val,int k)
{
for(;x<=n;x+=x&-x)c[k][x]+=val;
}
int main()
{
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++)scanf("%lld",&a[i]),a[i]=a[i]+a[i-1];
while(m--)
{
char s[2];
scanf("%s",s);
if(s[0]=='Q')
{
int xi,yi;
scanf("%d%d",&xi,&yi);
printf("%lld\n",a[yi]-a[xi-1]+(yi+1)*ask(yi,0)-ask(yi,1)-( xi*ask(xi-1,0)-ask(xi-1,1) ) );
}
else
{
int xi,yi,val;
scanf("%d%d%d",&xi,&yi,&val);
add(xi,val,0);
add(yi+1,-val,0);
add(xi,xi*val,1);
add(yi+1,-val*(yi+1),1);
}
}
}