基础操作(以和为例子)
inline void add(register int x, register int k)//在a[x]这个位置加上k
{
while (x <= n)
{
t[x] += k;
x += x & -x;
}
}
inline int ask(register int x)
{
register int sum = 0;
while (x >= 0)
{
sum += t[x];
x -= x & -x;
}
}
单点修改,区间查询
修改:
add(x);
查询:
ask(r) - ask(l - 1);
区间修改,单点查询
其实跟上面差不多,只不过用树状数组维护原数组的差分数组
修改:
add(l, k), add(r + 1, -d);
查询
ans = a[x] + ask(x);
区间修改,区间查询
这个比较麻烦,用一个树状数组t1维护差分数组$b_i$(前缀和),另一个树状数组t2维护$i * b_i$(前缀和)
修改:
add1(l, d), add1(r + 1, -d);
add2(l, l * d), add2(r + 1, -(r + 1) * d);
查询:
ans = (sum[r] + (r + 1) * ask1(r) -ask2(r)) - (sum[l - 1] + l * ask1(l - 1) -ask2(l - 1));