完全不知道该怎么用,看书稍微懂了点。
题意:
给定序列及操作,求区间和。
分析:
树状数组可以高效的求出连续一段元素之和或更新单个元素的值。但是无法高效的给某一个区间的所有元素同时加个值。
不能直接用树状数组求,就处理一下。用两个树状数组维护两个数据,一个维护前
i
项和,一个维护增加的值。设:
- 对于
bit0 来说,在 l 位置上加上−x∗(l−1) ,在 r+1 位置上加上 x∗r- 对于
bit1
来说,在
l
位置上加上
x ,在 r+1 位置上加上 −x 代码:
#include<cstdio> const int maxn = 300005; typedef long long ll; //[l,r] ll bit[2][maxn]; int v[maxn]; int n, q; ll sum(int i, int t) { ll tot = 0; while(i>0){ tot += bit[t][i]; i -= i&-i; } return tot; } void update(int i, int x, int t) { while(i <= n){ bit[t][i] += x; i += i&-i; } } int main (void) { scanf("%d%d",&n,&q); int a, b, c; for(int i = 1; i <= n; i++){ scanf("%d",&v[i]); update(i, v[i], 0); } for(int i = 0; i < q; i++){ getchar(); if(getchar()=='C'){ scanf("%d%d%d", &a, &b, &c); update(a, - c * (a - 1), 0); update(b + 1, c * b, 0);//bit0 update(a, c, 1); update(b + 1, - c,1); //bit1 }else{ scanf("%d%d",&a, &b); ll res = 0; res += sum(b, 0) + sum(b ,1) * b; res -=sum(a-1, 0) +sum(a-1, 1) * (a-1); printf("%I64d\n",res); } } }
如果操作得到的结果可以用 i 的
n 次多项式表示,那么就可以用 n+1 个树状数组维护了。1700ms比线段树快了700ms~
- 对于
bit1
来说,在
l
位置上加上