树状数组的第三种用法,区间修改,区间查询.
仔细讲下.假设我们要求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;
}
京公网安备 11010502036488号