BZOJ3155: Preprefix sum
Description
Input
第一行给出两个整数N,M。分别表示序列长度和操作个数
接下来一行有N个数,即给定的序列a1,a2,....an
接下来M行,每行对应一个操作,格式见题目描述
Output
对于每个询问操作,输出一行,表示所询问的SSi的值。
Sample Input
5 3
1 2 3 4 5
Query 5
Modify 3 2
Query 5
1 2 3 4 5
Query 5
Modify 3 2
Query 5
Sample Output
35
32
32
HINT
1<=N,M<=100000,且在任意时刻0<=Ai<=100000
A[i]+=v对Query(j)的影响是(j-i+1)*v -> (j+1)*v-i*v
所以用两个树状数组维护Σv和Σi*v即可。
#include<cstdio> #include<cctype> #include<queue> #include<cmath> #include<cstring> #include<algorithm> #define rep(i,s,t) for(int i=s;i<=t;i++) #define dwn(i,s,t) for(int i=s;i>=t;i--) #define ren for(int i=first[x];i!=-1;i=next[i]) using namespace std; const int BufferSize=1<<16; char buffer[BufferSize],*head,*tail; inline char Getchar() { if(head==tail) { int l=fread(buffer,1,BufferSize,stdin); tail=(head=buffer)+l; } return *head++; } inline int read() { int x=0,f=1;char c=Getchar(); for(;!isdigit(c);c=Getchar()) if(c=='-') f=-1; for(;isdigit(c);c=Getchar()) x=x*10+c-'0'; return x*f; } const int maxn=100010; typedef long long ll; ll A[maxn],sumv1[maxn],sumv2[maxn]; int n,m; void add1(int x,ll v) { for(;x<=n;x+=x&-x) sumv1[x]+=v; } ll sum1(int x) { ll res=0; for(;x;x-=x&-x) res+=sumv1[x]; return res; } void add2(int x,ll v) { for(;x<=n;x+=x&-x) sumv2[x]+=v; } ll sum2(int x) { ll res=0; for(;x;x-=x&-x) res+=sumv2[x]; return res; } int main() { n=read(),m=read(); rep(i,1,n) A[i]=read(),add1(i,A[i]),add2(i,A[i]*i); while(m--) { char c=Getchar();while(!isalpha(c)) c=Getchar(); int x=read(); if(c=='Q') printf("%lld\n",sum1(x)*(x+1)-sum2(x)); else { ll v=read();add1(x,v-A[x]);add2(x,(v-A[x])*x); A[x]=v; } } return 0; }