bzoj3155Preprefix sum

bzoj3155Preprefix sum

题意:

询问一个数组前缀和数组的前缀和,支持单点修改。

题解:

SSi=sigma(i,1,n)(n-i+1)*ai=(n+1)*Si-sigma(i,1,n)i*ai。然后就只要用树状数组维护ai和i*ai的前缀和就行了。

代码:

 1 #include <cstdio>
 2 #include <cstring>
 3 #include <algorithm>
 4 #define inc(i,j,k) for(int i=j;i<=k;i++)
 5 #define maxn 100010
 6 #define lb(x) x&-x
 7 #define ll long long
 8 using namespace std;
 9 
10 ll v[maxn][2],sm[maxn][2]; int n,m; char s[10];
11 inline int read(){
12     char ch=getchar(); int f=1,x=0;
13     while(ch<'0'||ch>'9'){if(ch=='-')f=-1; ch=getchar();} while(ch>='0'&&ch<='9')x=x*10+ch-'0',ch=getchar();
14     return f*x;
15 }
16 void update(int x,ll val,bool b){while(x<=n)sm[x][b]+=val,x+=lb(x);}
17 ll query(int x,bool b){ll q=0; while(x)q+=sm[x][b],x-=lb(x); return q;}
18 int main(){
19     n=read(); m=read();
20     inc(i,1,n)v[i][0]=(ll)read(),v[i][1]=(ll)i*v[i][0],update(i,v[i][0],0),update(i,v[i][1],1);
21     inc(i,1,m){
22         scanf("%s",s);
23         if(s[0]=='Q'){int a=read(); printf("%lld\n",query(a,0)*(a+1)-query(a,1));}
24         if(s[0]=='M'){
25             int a=read(); ll b=(ll)read();
26             update(a,b-v[a][0],0); v[a][0]=b; update(a,b*a-v[a][1],1); v[a][1]=b*a;
27         }
28     }
29     return 0;
30 }

 

20160630

posted @ 2016-07-30 13:28  YuanZiming  阅读(333)  评论(0编辑  收藏  举报