Algorithm-Bit
algorithm, 数据结构, 树状数组
Word Count: 682(words)
Read Count: 3(minutes)
【数据结构】树状数组
引言
树状数组可以说是最好写,也是最好用的一种数据结构了~
树状数组
概览
树状数组是用数组存储的,它并没有显式的树形结构,而是用数组下表的二进制表示中最低位1的位置构建的一个隐式的树形结构。
这里不盗图了,要有版权意识~所以,更形象的展示可以参考这个博客中的AB图。
关于lowbit
lowbit当然不是low逼的意思啦~
lowbit(x)=x&-x,要理解这个,首先要知道计算机中补码的概念。如+8,因为正数的补码为其本身,所以其的二级制表示为01000(最高位是符号位)。而-8的补码将+8的所有位(包括符号位)取反,然后加1的结果,也就是11000。
所以,这个函数的作用就是求x最低位1所对应的数字,lowbit(8)=1000=8。
操作
树状数组支持单点修改,区间查询操作。
其中单点修改是增量修改,区间查询支持具有区间可合并性质的属性。
当然,经过改造也可以进行区间修改,大致思想就是引入一个delta数组,delta[i]表示区间 [i, n] 的共同增量,然后剩下的就不多说了,可以自行推导了~
代码
单点修改+区间查询
1 2 3 4 5 6 7 8 9
| void update(int x, int ad) { for (; x <= n; x += lowbit(x)) c[x] += ad; }
int getsum(int x) { int sum = 0; for (; x ;x -= lowbit(x)) sum += c[x]; return sum; }
|
应用
找个比较水的题,poj3321,用树的先序遍历构建成数组,然后在上面跑裸的树状数组就好了~
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69
| #include <iostream> #include <cstdio> #include <cstdlib> #include <cstring>
using namespace std;
#define N 100010 #define lowbit(x) x&-x
int head[N], nxt[N], to[N]; int c[N]; int cnt, num; int n, m; int in[N], out[N];
void update(int x, int ad) { for (; x <= n; x += lowbit(x)) c[x] += ad; }
int getsum(int x) { int sum = 0; for (; x ;x -= lowbit(x)) sum += c[x]; return sum; }
void add(int u, int v) { to[cnt] = v; nxt[cnt] = head[u]; head[u] = cnt++; }
void dfs(int x) { in[x] = num; for (int i = head[x]; ~i; i = nxt[i]) { update(++num, 1); dfs(to[i]); } out[x] = num; }
int main() { memset(head, -1, sizeof head); memset(nxt, -1, sizeof nxt); cnt = num = 0; scanf("%d", &n); for (int i = 1, a, b; i < n; i++) { scanf("%d%d", &a, &b); add(a, b); } update(++num, 1); dfs(1);
scanf("%d", &m); char str[5]; int x; getchar(); while (m--) { scanf("%s%d", str, &x); if (str[0] == 'Q') { printf("%d\n", getsum(out[x]) - getsum(in[x] - 1)); } else { if (getsum(in[x]) - getsum(in[x] - 1) == 1) update(in[x], -1); else update(in[x], 1); } } return 0; }
|
(待更新…)