bzoj3155: Preprefix sum

来源:互联网 发布:coord10软件下载 编辑:程序博客网 时间:2024/06/02 04:51

我们考虑把一个数字加某个值

a1 a2 a3 a4 a5a6
+t
s1 s2 s3s4s5 s6
+t +t+t+t
ss1 ss2 ss3 ss4 ss5 ss6
+t +2t+3t+4t

设d[i]表示从i开始ss[i]依次加d[i],d[i]*2,d[i]*3....

d[i]对于ss[n]的贡献为d[i]*(n-i+1)

设原数组为org

ss[n] = sigma(org[i]) + sigma(d[i]*(n-i+1))

=sigma(org[i]) + sigma(d[i])*(n+1) - sigma(d[i]*i)

用树状数组维护d[i]和的d[i]*i即可

#include <stdio.h>#define MAXN 100003int n, Q;int a[MAXN], d[MAXN];int lowbit(int x){    return x & (-x);}void plus(long long *f, int p, long long x){    int i;    for (i = p; i <= n; i += lowbit(i))        f[i] += x;}long long query(long long *f, int p){    long long ans = 0;    int i;    for (i = p; i; i -= lowbit(i))        ans += f[i];    return ans;}long long s[MAXN], d0[MAXN], d1[MAXN];int main(){    scanf("%d%d", &n, &Q);    int i;    long long tmp = 0;    for (i = 1; i <= n; ++i)    {        scanf("%d", &a[i]);        s[i] = s[i - 1] + (tmp += a[i]);    }    while (Q--)    {        char opt[10];        scanf("%s", opt);        if (opt[0] == 'Q')        {            int p;            scanf("%d", &p);            long long ans = s[p];            ans += query(d0, p) * (p + 1);            ans -= query(d1, p);#ifdef ONLINE_JUDGE            printf("%lld\n", ans);#else            printf("%I64d\n", ans);#endif        }        else        {            int p, x;            scanf("%d%d", &p, &x);            long long t = x - a[p];            plus(d0, p, t);            plus(d1, p, t * p);            d[p] += t;            a[p] = x;        }    }    return 0;}


0 0
原创粉丝点击