BZOJ 3155: Preprefix sum

时间:2021-09-11 19:36:27

大意:给一个数组,先求出SUM[I],然后动态的求出1-I的SUM[I]的和,

这题得化公式:

树状数组维护两个和:SUM(A[I])(1<=I<=X);

SUM(A[I]*(N-I+1)) (1<=I<=X);

答案就是:SUM(A[I]*(N-I+1))-SUM[A[I]]*(N-X) (1<=I<=X);

#include<stdio.h>
#include<string.h>
#include<algorithm>
#include<cmath>
using namespace std;
typedef long long ll;
const int N=;
ll s[N],t[N];
int a[N];
int n; int lowbit(int x)
{
return x&(-x);
}
void update1(int x,ll v)
{
while (x<=n)
{
s[x]+=v;
x+=lowbit(x);
}
} void update2(int x,ll v)
{
while (x<=n)
{
t[x]+=v;
x+=lowbit(x);
}
} ll sum1(int x)
{
ll ans=;
while (x)
{
ans+=s[x];
x-=lowbit(x);
}
return ans;
}
ll sum2(int x)
{
ll ans=;
while (x)
{
ans+=t[x];
x-=lowbit(x);
}
return ans;
} int main()
{
int m;
char s[];
scanf("%d%d",&n,&m);
for (int i=;i<=n;i++)
{
scanf("%d",&a[i]);
update1(i,a[i]);
update2(i,(ll)a[i]*(n-i+));
} while (m--)
{
int x,y;
scanf("%s%d",s,&x);
if (s[]=='Q')
{
printf("%lld\n",sum2(x)-sum1(x)*(n-x));
}
else
{
scanf("%d",&y);
update1(x,y-a[x]);
update2(x,(ll)(y-a[x])*(n-x+));
a[x]=y;
}
}
return ;
}