树状数组
那些年我用树状数组干过的事:
- 求前缀和
- 给定整数序列的第i位,在当前还未出现的元素中是排在第几个
P5367 【模板】康托展开 / 计算数列在全排列中的排名 - 1e6的树上节点修改+查询子树上所有节点上的点权和
板子
namespace BIT {//树状数组
int bit[N];
int lowbit(int x) { return x & (-x); }
void add(int x, int val) {
for (; x <= N; x += lowbit(x)) {
bit[x] += val;
}
}
int ask(int x) {
int res = 0;
for (; x; x -= lowbit(x)) {
res += bit[x];
}
return res;
}
}
using namespace BIT;
1e6的树上节点修改+查询子树上所有节点上的点权和
#include <bits/stdc++.h>
using namespace std;
const int N = 1e6 + 10;
vector<int> e[N];
int a[N];
int n, m, root;
int l[N], r[N], cnt = 0;
namespace BIT {//树状数组
int bit[N];
int lowbit(int x) { return x & (-x); }
void add(int x, int val) {
for (; x <= N; x += lowbit(x)) {
bit[x] += val;
}
}
int ask(int x) {
int res = 0;
for (; x; x -= lowbit(x)) {
res += bit[x];
}
return res;
}
}
using namespace BIT;
void dfs(int u, int f) {
l[u] = ++cnt;
add(l[u], a[u]);
for (auto v:e[u]) {
if (v == f)continue;
dfs(v, u);
}
r[u] = cnt;
}
int main() {
ios::sync_with_stdio(0);
cin >> n >> m >> root;
for (int i = 1; i <= n; ++i) {
cin >> a[i];
}
for (int i = 1, u, v; i < n; ++i) {
cin >> u >> v;
e[u].push_back(v);
e[v].push_back(u);
}
dfs(root, 0);
int op, u, x;
while (m--) {
cin >> op;
if (op == 1) {
cin >> u >> x;
add(l[u], x);
//u节点的权值加上x
} else {
cin >> u;
cout << ask(r[u]) - ask(l[u] - 1) << endl;
//统计u节点包括其子树上所有的节点的和
}
}
return 0;
}