树状数组的第三种用法,区间修改,区间查询.
仔细讲下.假设我们要求a[l-r]里面的和,而我们知道a[l]=d[1-l].

用代码表示a[l~r]的和就是:
int sum=0;
for(int i=l;i<=r;i++)
{
    for(int j=1;j<=i;j++)
    {
        sum+=a[j];
    }
}
()表示对1到n求和
n*a[1]+(n-1)*a[2]+...+a[n]=n*()*d[i]-()(d[i]*(i-1)).

我们要这样想树状数组的功能是对1到n求和.
代码如下:

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const ll N=1e5+5;
ll a[N],d[N],sum1[N],sum2[N],n;
ll lowbit(ll x)
{
    return x&(-x);
}

void insert(ll pos,ll val)
{
    ll x=pos;
    while(pos<=n)
    {
        sum1[pos]+=val;
        sum2[pos]+=val*(x-1);
        pos+=lowbit(pos);
    }
}

ll query(ll pos)
{
    ll res=0;
    ll x=pos;
    while(pos>0)
    {
        res+=(x*sum1[pos]-sum2[pos]);
        pos-=lowbit(pos);
    }
    return res;
}

int main()
{
    ll m;
    scanf("%lld%lld",&n,&m);
    for(ll i=1;i<=n;i++)
    {
        scanf("%lld",&a[i]);
    }
    for(ll i=1;i<=n;i++)
    {
        insert(i,a[i]-a[i-1]);
    }
    while(m--)
    {
        string s;
        ll l,r,x;
        cin>>s;
        if(s=="Q")
        {
            cin>>l>>r;
            cout<<query(r)-query(l-1)<<endl;
        }
        else
        {
            cin>>l>>r>>x;
            insert(l,x);
            insert(r+1,-x);
        }
    }
    return 0;
}