树状数组
树状数组可用于动态查询数组的前缀和,其支持单点修改、区间修改、单点查询、区间查询操作。
树状数组的根本思想其实是分块,把每个区间分成最多
我们可以这样分块,观察
其中 a 表示原数组,c 表示树状数组。
那么我们如何得到这个数的二进制中 query 操作。
而对于单点修改,其实就是区间查询的逆运算,不难发现只要每次先 update 操作。
然后对于区间修改,我们可以对树状数组进行差分,这样就可以进行单点查询。如果要区间修改与区间查询,可使用线段树。
Code
long long a[N], sum[N];
// ----------------------------
int lowbit(int x) {
return (x & -x);
}
long long query(int x) {
long long res = 0;
while (x) {
res += sum[x];
x -= lowbit(x);
}
return res;
}
void update(int x, int k, int n) {
while (x <= n) {
sum[x] += k;
x += lowbit(x);
}
}
// ----------------------------
int n, m; read(n, m);
for (int i = 1; i <= n; i++) {
read(a[i]);
update(i, a[i], n);
}
// ----------------------------
int op, x, k, y;
while (m--) {
read(op);
if (op == 1) {
read(x, k);
update(x, k, n);
}
else {
read(x, y);
print(query(y) - query(x - 1));
putchar('\n');
}
}