[bzoj-3155]Preprefix sum 题解

来源:互联网 发布:王励勤多娜 知乎 编辑:程序博客网 时间:2024/06/01 10:25

题目传送门
题意解析:题目给了一个a序列,并且定义s为a序列的前缀和,ss为s序列的前缀和,然后有两种操作,一种是查询ss[i]的值,还有一种是修改a[i]。


My opinion:明显的数据结构题,但是怎么维护是一个问题,我们列出a,s,ss就会发现一些现象。
a a1 a2 a3 a4 a5 a6 …… an
s a1 a1+a2 a1+a2+a3 …… a1+a2+……+an
ss a1 2a1+a2 3a1+2a2+a3 …… na1+(n-1)a2+……+an
从上我们可以看出,每一个ai在一个ssj中(i<=j),ai有(j-i+1)个
所以这题我们只需要维护ai的前缀和和(n-i+1)*ai的前缀和就可以了。
最后答案的计算就是(n-i+1)*ai的前缀和减去ai的前缀和乘上(n-i)。
所以我们可以用各种数据结构维护,不过因为维护的区间是1-i(有可能没啥用),所以我用了树状数组。
总结:
1、输入,并加入树状数组。
2、对于每个操作做出相应的反应。


结构体大法好:

#include<iostream>#include<cstdio>#include<cmath>#include<cstring>#include<algorithm>#define rep(i,a,n) for (int i=a;i<=n;i++)#define per(i,a,n) for (int i=a;i>=n;i--)#define Clear(a,x) memset(a,x,sizeof(a))#define ll long long#define INF 2000000000#define eps 1e-8using namespace std;int read(){    int x=0,f=1;     char ch=getchar();    while (ch<'0'||ch>'9') f=ch=='-'?-1:f,ch=getchar();    while (ch>='0'&&ch<='9') x=x*10+ch-'0',ch=getchar();    return x*f;}const int maxn=100005;int a[maxn];int lowbit(int x){    return x&(-x);}int n,m;struct tree{    ll tr[maxn];    inline void add(int x,ll d){        for (int i=x;i<=n;i+=lowbit(i))            tr[i]+=d;    }    inline ll sum(int x){        ll ans=0;        for (int i=x;i;i-=lowbit(i))            ans+=tr[i];        return ans;    }}tr1,tr2;int main(){    n=read(),m=read();    rep(i,1,n){        a[i]=read();        tr1.add(i,a[i]);        tr2.add(i,(ll)(n-i+1)*a[i]);        }    rep(i,1,m){        char op[10];        scanf("%s",op);        if (op[0]=='Q'){            int x=read();            printf("%lld\n",tr2.sum(x)-tr1.sum(x)*(n-x));        }else{            int x=read(),y=read();            tr1.add(x,y-a[x]);            tr2.add(x,(ll)(n-x+1)*(y-a[x]));            a[x]=y;        }    }    return 0;}