bzoj3155: Preprefix sum

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

a1 a2 a3 a4 a5a6
+t
s1 s2 s3s4 s5 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 100003
int 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;
}


阅读更多

没有更多推荐了,返回首页