一维树状数组
有手就行。
#include <bits/stdc++.h>
using namespace std;
const int N = 1000010;
int n, a[N];
inline int lowbit(int x) { return x & (-x); }
int ask(int x) {
int res = 0;
for (; x; x -= lowbit(x)) res += a[x];
return res;
}
void add(int x, int val) {
for (; x <= n; x += lowbit(x)) a[x] += val;
}
int query(int l, int r) {
return ask(r) - ask(l - 1);
}
二维树状数组
下面这个代码是用来处理差分数据的,其实单纯处理二维求和和单点修改更简单些。
#include<bits/stdc++.h>
using namespace std;
const int N = 1010;
int n, m;
int a[N][N];//原数组
int d[N][N];//差分数组
inline int lowbit(int x) { return x & (-x); }
//对差分数组某处加上值
void add(int x, int y, int val) {
for (; x <= n; x += lowbit(x))
for (; y <= m; y += lowbit(y))
d[x][y] += val;
}
//对矩阵a (x1,y1)到(x2,y2)集体加上v
void real_add(int x1, int y1, int x2, int y2, int val) {
add( x1 , y1 , val);
add( x1 , y2+1, -val);
add(x2+1, y1 , -val);
add(x2+1, y2+1, val);
}
//查询a[i][j]的值
int query(int x, int y) {
int ans = 0;
for (; x; x -= lowbit(x))
for (; y; y -= lowbit(y))
ans += d[x][y];
return ans;
}
ST表
取对数不要用数学库的对数函数,那玩意复杂度不是常数,还是预处理比较好。
#include <bits/stdc++.h>
using namespace std;
const int N = 100010;
int n;
//初始数据
int a[N];
//ST表
int ST[N][25], lg[N];
void init()
{
//log预处理
lg[1] = 0;
for (int i = 2; i <= n; i++)
lg[i] = lg[i / 2] + 1;
//ST表预处理
for (int i = 1; i <= n; ++i)
ST[i][0] = a[i];
for (int k = 1; k <= 20; ++k)
for (int i = 1; i + (1 << k) - 1 <= n; ++i)
ST[i][k] = max(ST[i][k - 1], ST[i + (1 << (k - 1))][k - 1]);
}
//询问
inline int query(int l, int r) {
int k = lg[r - l + 1];
return max(ST[l][k], ST[r - (1 << k) + 1][k]);
}