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

Sample Output

35
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;    
}
View Code

 

posted @ 2015-12-10 10:28  wzj_is_a_juruo  阅读(189)  评论(0编辑  收藏  举报