[学习笔记] 树状数组区间加+区间求和

来源:互联网 发布:修改软件下载 编辑:程序博客网 时间:2024/06/16 13:22
  • bi=aiai1,ci=(i1)×bi,则:
    i=1nai
    =a1+a2++an
    =i=11bi+i=12bi++i=1nbi
    =n×i=1nbii=1n(i1)×bi
    =n×i=1nbii=1nci
  • 我们用两个树状数组分别维护bi,ci
    1.令区间[l,r]加上x,即为
    bl+=x,br+1=x
    cl+=(l1)×x,cr+1=r×x

    2.询问区间[l,r]的和,即为
    r×i=1rbii=1rci(l1)×i=1l1bi+i=1l1ci
  • 代码
const int N = 1e5 + 5;ll b[N], c[N]; int a[N], n, m;inline void Modify(ll *s, int x, ll y){    for (; x <= n; x += x & -x)        s[x] += y;}inline ll Query(ll *s, int x){    ll res = 0;    for (; x; x ^= x & -x)        res += s[x];    return res;}int main(){    n = get(); m = get(); int k, l, r, x;    for (int i = 1; i <= n; ++i)    {        a[i] = get();        Modify(b, i, a[i] - a[i - 1]);        Modify(c, i, 1ll * (i - 1) * (a[i] - a[i - 1]));    }    while (m--)    {        k = get(); l = get(); r = get();        if (k & 1)        {            x = get();            Modify(b, l, x);             Modify(b, r + 1, -x);            Modify(c, l, 1ll * (l - 1) * x);            Modify(c, r + 1, -1ll * r * x);         }        else         {            --l;            put(Query(b, r) * r - Query(c, r)              - Query(b, l) * l + Query(c, l));            putchar('\n');         }    }}