什么是树状数组?让这个12岁年轻人为你讲解
Part 1 我学它干啥?
求和
Part 2 lowbit
long long lowbit(long long x) {
return x & -x;
}
Part 3 树状数组
结构
bit[i] = 在数组a中从 i - lowbit(i) + 1 到 i 求和
更改单个数值
bit[3] 对应 a的[3, 3] 的和
bit[4] 对应 a的[1, 4] 的和
bit[8] 对应 a的[1, 8] 的和
bit[16] 对应 a的[1, 16] 的和
以上四个bit中的值都需要更改
void add(int index, long long value) {
while (index <= n) { // 更新直到最大的块
node[index] += value; // 更新当前的块
index += lowbit(index); // 加上一个自己的长度,补上空缺,得到下一个块
}
}
区间求和
long long sum(int index) {
long long sum = 0;
while (index > 0) {
sum += node[index];
index -= lowbit(index);
}
return sum;
}
构造
时间复杂度对比
代码
//
// Created by Cat-shao on 2021/2/9.
//
#include <cstdio>
#include <cstring>
using namespace std;
const long long MAX_N = 5000100;
long long lowbit(long long x) {
return x & -x;
}
class BIT {
public:
long long node[MAX_N], n;
BIT(int _n) {
memset(node, 0, sizeof(node));
n = _n;
}
long long sum(int index) {
long long sum = 0;
while (index > 0) {
sum += node[index];
index -= lowbit(index);
}
return sum;
}
void add(int index, long long value) {
while (index <= n) {
node[index] += value;
index += lowbit(index);
}
}
};
int BITMain()
{
// https://www.luogu.com.cn/problem/P3374
int n, m, op, x, y;
long long value;
scanf("%d%d", &n, &m);
BIT tree = BIT(n);
for (int i = 1; i <= n; ++i) {
scanf("%lld", &value);
tree.add(i, value);
}
for (int i = 0; i < m; ++i) {
scanf("%d%d%d", &op, &x, &y);
if (op == 1) {
tree.add(x, y);
} else if (op == 2) {
printf("%lld\n", (tree.sum(y) - tree.sum(x - 1)));
}
}
return 0;
}
int main()
{
BITMain();
}
评论