layout: posttitle: 支持区间修改的树状数组 |oyxBlogcategories: [树状数组, 模板]description: 树状数组的变种keywords: 树状数组, 模板
原理
对于一个数组
那么对于数组a的前缀和有
进一步的:
展开括号内
即为
因此维护一个前缀和数组需要维护两个差分前缀和
这里使用两个树状数组对上述差分数组前缀和维护,分别命名为
实现
首先明确基本树状数组的两个基本操作:区间查询和单调查询。使用树状数组维护前缀和:
- 区间查询
,1到k之间的前缀和
- 单点修改
,
那么对于本文中的支持区间修改的树状数组有以下操作:1.区间修改
操作
基本树状数组
实现了
int
初始化
void
区间修改
//[l,r]区间修改+xvoid add(int l, int r, int x) { add(tr, l, x); add(tr, r + 1, -x); add(tr1, l, 1ll * (l - 1) * x); add(tr1, r + 1, 1ll * r * (-x));}
区间查询
查询
//区间查询原数组sum(a[1,k])ll querysum(int k) { return (1ll * query(tr, k) * k) - query(tr1, k);}
区间修改
在
//[l,r]区间修改+xvoid add(int l, int r, int x) { add(tr, l, x); add(tr, r + 1, -x); add(tr1, l, 1ll * (l - 1) * x);//防止暴int add(tr1, r + 1, 1ll * r * (-x));}
复杂度分析
实质是两个树状数组来维护着差分前缀和,其中空间是3倍的区间长度,
- 区间同加x
- 区间查询
- 单点查询
- 单调同加x
相比线段树空间复杂度
编程复杂度差不多(都好难orz)
整合模板
题目传送门
#define judge
参考链接:树状数组区间加等差数列