有的时候,从现实生活中抽象出来的模型中结点被赋予了一个权值,而求解目标是动态统计子树的权值和,如果通过直接遍历求解,耗费的时间复杂度是O(n),但问题是,若结点的权值在不断的发生变化,那么相关的权值和也在不断的发生着变化,如此这般通过不断遍历实现的方法时间复杂度就会很高,由此衍生出了树状数组的计算方法,可以实现不断对数组结点的权值进行查询和维护。查询和维护的时间复杂度为O(log n);
树状数组:
主要有三个函数组成:
函数1:
主要用于对数组结点的划分
int lowbit(int x) {
return x & (-x);
}
函数2:
数组的维护函数:
void change(int x, int k) {
while (x <= n) {
sum[x] += k;
x += lowbit(x);
}
}
函数3:
主要是对数组的查询
int getsum(int x) {
int ans = 0;
while (x) {
ans += sum[x];
x -= lowbit(x);
}
return ans;
}
代码:
#include<iostream>
#include<cstdio>
#include<algorithm>
using namespace std;
const int maxn = 10010;
int num[maxn], sum[maxn], n;
int lowbit(int x) {
return x & (-x);
}
void change(int x, int k) {
while (x <= n) {
sum[x] += k;
x += lowbit(x);
}
}
int getsum(int x) {
int ans = 0;
while (x) {
ans += sum[x];
x -= lowbit(x);
}
return ans;
}
int main()
{
ios::sync_with_stdio(false);
cin.tie(0); cout.tie(0);
int i, l, r;
cin >> n;
for (i = 1; i <= n; ++i) {
num[i] = i;
change(i, i);
}
int T;
cin >> T;
while (T--) {
cin >> l >> r;
cout << getsum(r) - getsum(l - 1) << endl;
}
return 0;
}