洛谷P3368 树状数组2
文章目录
题目链接
https://www.luogu.com.cn/problem/P3368
树状数组
学习树状数组:https://www.youtube.com/watch?v=v_wj_mOAlig。
首先简单介绍一下树状数组,以及为什么要使用树状数组。
假设有一个数组,我们需要对该数组执行如下操作(以下全部假设数组下标从1开始):
- 求前i项的和。
- 将第i项元素加上某个给定的值。
如果使用普通的数组,执行第一个操作的时间为 O ( n ) O(n) O(n),执行第二个操作的时间为 O ( 1 ) O(1) O(1)。
如果用数组保存的内容为前缀和,执行第一个操作的时间为 O ( 1 ) O(1) O(1),执行第二个操作的时间为 O ( n ) O(n) O(n)。
而使用树状数组,这两个操作的时间都为 O ( log 2 n ) O(\log_2n) O(log2n)。
关于树状数组的原理,请观看上面链接中的视频或寻找其他资料。
下面是C++的简单实现代码:
int n;
int arr[500001];
inline int last_bit(int num) {
return num & (-num);
}
// return the sum of [1, index]
int sum(int index) {
int res = 0;
while (index) {
res += arr[index];
index -= last_bit(index);
}
return res;
}
// plus value to the element of index of arr
void add(int index, int value) {
while (index <= n) {
arr[index] += value;
index += last_bit(index);
}
}
其中 a r r arr arr的第一个元素(下标为 0 0 0)不使用, n n n