BZOJ 3155: Preprefix sum
大意:给一个数组,先求出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=110001; 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=0; while (x) { ans+=s[x]; x-=lowbit(x); } return ans; } ll sum2(int x) { ll ans=0; while (x) { ans+=t[x]; x-=lowbit(x); } return ans; } int main() { int m; char s[8]; scanf("%d%d",&n,&m); for (int i=1;i<=n;i++) { scanf("%d",&a[i]); update1(i,a[i]); update2(i,(ll)a[i]*(n-i+1)); } while (m--) { int x,y; scanf("%s%d",s,&x); if (s[0]=='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+1)); a[x]=y; } } return 0; }
随性Code