题目
http://poj.org/problem?id=3468
解题思路
对于每条指令“C l r d”,把
b[l]
b
[
l
]
加上
d
d
,再把减去
d
d
。
数组的前缀和
∑xi=1b[i]
∑
i
=
1
x
b
[
i
]
就是经过这些指令后
a[x]
a
[
x
]
增加的值。
那么序列
a
a
的前缀和整体增加的值就是:
上式可以改写为:
我们可以用一个树状数组,维护 i∗b[i] i ∗ b [ i ] 的前缀和 ∑xi=1i∗b[i] ∑ i = 1 x i ∗ b [ i ] ,上式就可以直接查询、计算。
代码
#include<cstdio>
#include<algorithm>
#include<string>
#include<iostream>
using namespace std;
string s; int n,m,aa,l,r,d; long long ans,sum[100010],c[2][100010];
long long ask(int k,int x){
long long ans=0;
for (;x;x-=x&-x) ans+=c[k][x]; return ans;
}
void add(int k,int x,int y){
for (;x<=n;x+=x&-x) c[k][x]+=y;
}
int main()
{
scanf("%d%d",&n,&m);
for (int i=1;i<=n;i++){
scanf("%d",&aa); sum[i]=sum[i-1]+aa;
}
for (int i=1;i<=m;i++)
{
cin>>s; scanf("%d%d",&l,&r);
if (s[0]=='C') {
scanf("%d",&d);
add(0,l,d); add(0,r+1,-d); add(1,l,l*d); add(1,r+1,-(r+1)*d);
} else{
ans=sum[r]+(r+1)*ask(0,r)-ask(1,r);
ans-=sum[l-1]+l*ask(0,l-1)-ask(1,l-1);
printf("%lld\n",ans);
}
}
}