树状数组的区间修改与区间查询
2016-11-23 21:59
190 查看
我们知道,线段树实现区间修改和查询可以通过lazy标记来实现
今天学到一个新姿势,树状数组也可以实现区间修改和查询
我们引入delta数组delta[i]表示区间[i, n]的共同增量 于是修改区间[l, r]时修改delta[l]和delta[r + 1]即可
(就是差分的思路)
查询的时候是查询区间 [l, r] 的和 即sum[r] - sum[l - 1] 所以现在的问题是求sum[i]
其中 sigma( a[x] ) 是可以预处理出来的 于是只需要维护 delta[x] 与 delta[x] * x 的前缀和(作为两个树状数组就可以了)
今天学到一个新姿势,树状数组也可以实现区间修改和查询
我们引入delta数组delta[i]表示区间[i, n]的共同增量 于是修改区间[l, r]时修改delta[l]和delta[r + 1]即可
(就是差分的思路)
查询的时候是查询区间 [l, r] 的和 即sum[r] - sum[l - 1] 所以现在的问题是求sum[i]
sum[i] = a[1]+...+a[i] + delta[1]*i + delta[2]*(i - 1) + delta[3]*(i - 2)+...+delta[i]*1 // a[i]为原始数组 = sigma( a[x] ) + sigma( delta[x] * (i + 1 - x) ) = sigma( a[x] ) + (i + 1) * sigma( delta[x] ) - sigma( delta[x] * x )
其中 sigma( a[x] ) 是可以预处理出来的 于是只需要维护 delta[x] 与 delta[x] * x 的前缀和(作为两个树状数组就可以了)
#include <cstdio> #include <iostream> #define lowbit(i) (i & (-i)) using namespace std; int readint() { int sign = 1, n = 0; char c = getchar(); while(c < '0' || c > '9'){ if(c == '-') sign = -1; c = getchar(); } while(c >= '0' && c <= '9') { n = n*10 + c-'0'; c = getchar(); } return sign*n; } const int Nmax = 200100; int N, Q; long long delta[Nmax]; // delta的前缀和 long long deltai[Nmax]; // delta * i的前缀和 long long sum[Nmax]; // 原始前缀和 long long Query(long long *array, int pos) { long long temp = 0ll; while(pos > 0) { temp += array[pos]; pos -= lowbit(pos); } return temp; } void Update(long long *array, int pos, int x) { while(pos <= N) { array[pos] += x; pos += lowbit(pos); } } int main() { N = readint(); for(int i = 1; i <= N; ++i) { int x = readint(); sum[i] = sum[i - 1] + x; } Q = readint(); while(Q--) { int sign = readint(); if(sign == 1) // 修改:把[l, r]区间均加上x { int l = readint(), r = readint(), x = readint(); Update(delta, l, x); Update(delta, r+1, -x); Update(deltai, l, x * l); Update(deltai, r+1, -x * (r+1)); } else // 查询:[l, r]区间和 { int l = readint(), r = readint(); long long suml = sum[l - 1] + l * Query(delta, l - 1) - Query(deltai, l - 1); long long sumr = sum[r] + (r + 1) * Query(delta, r) - Query(deltai, r); printf("%lld\n", sumr - suml); } } return 0; }
相关文章推荐
- P3368 【模板】树状数组 2 单点查询与区间修改
- 树状数组 --区间查询+区间修改
- [模板]树状数组(区间修改单点查询)
- 【树状数组区间修改单点查询+分组】HDU 4267 A Simple Problem with Integers
- 【转】【小结】树状数组的区间修改与区间查询
- [模板]-树状数组③-区间修改+区间查询
- 树状数组处理区间查询和区间修改的问题
- UVALive 4730 - Kingdom 树状数组区间修改单点查询
- hdu p1556 树状数组的区间修改,单点查询。
- 可以区间修改区间查询的树状数组云云
- 树状数组进阶(区间修改+单点查询)
- hdu 4970 Killing Monsters 【树状数组(区间修改,点查询)】
- 【bzoj3110】[Zjoi2013]K大数查询 整体二分+树状数组区间修改
- 【黑科技】用树状数组解决区间修改查询问题
- 【BZOJ3110】【整体二分+树状数组区间修改/线段树】K大数查询
- 树状数组 区间修改+区间查询
- POJ 3468 A Simple Problem with Integers (树状数组) (区间修改+区间查询)
- 【树状数组区间修改单点查询】HDU 4031 Attack
- 树状数组的应用(区间修改,区间查询,多维树状数组)
- 【BZOJ 3110】 [Zjoi2013]K大数查询 整体二分+树状数组区间修改