算法模板之树状数组
Posted backkom-buaa
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了算法模板之树状数组相关的知识,希望对你有一定的参考价值。
什么是树状数组?
? 树状数组就是通过数组来模拟一种树形结构,这种树形结构能够维护区间信息。同样类似的数据结构还有线段树,线段树与树状数组相比,它的结点更多,也就是说线段树的常数更大。
? 线段树是通过把区间二分来维护区间的信息,而树状数组是通过lowbit来维护区间的信息。
? 以树状数组维护区间和为例,对于树状数组c而言,$ c[i]= a[i-2^k+1]+a[i-2^k+2]+...+a[i]$ ,其中数组a存储的是数据,k就是lowbit位。
? lowbit: 一个非零二进制数中最小的不为零的位。
C++板子
#include<bits/stdc++.h>
using namespace std;
/**
以维护区间和的场景为例
**/
const int N = 1e5+2;
int a[N],b[N];
int lowbit(int x) { return x & (-x); }
/*
区间查询,单点修改
*/
int query(int x) {
int ret = 0;
for(int i=x;i;i-=lowbit(i)){
ret += b[i];
}
return ret;
}
void add(int x,int d) {
for(int i=x;i<=n;i+=lowbit(i)) {
b[i]+=d;
}
}
int main() {
//先把每个点的信息添加到树状数组内
for(int i=0;i<n;i++) {
cin >> a[i];
add(i,a[i]);
}
//查询区间[a,b]的内容
cout << query(b) - query(a-1);
}
JAVA板子
public class Main {
public static void main(String[] args) {
}
private static int lowbit(int x) {
return x & (-x);
}
private static class binary_indexed_tree {
private int n;
private int a[];
private int b[];
public binary_indexed_tree() {
binary_indexed_tree(1000);
}
public binary_indexed_tree(int n) {
a = new int[n];
b = new int[n];
this.n = n;
}
// 单点修改
public void add(int x,int d) {
for(int i=x;i<=n;i+=lowbit(i)) {
b[i] += d;
}
}
//区间查询
public int query(int x) {
int ret = 0;
for(int i=x ;i; i-=lowbit(i)) {
ret += b[i];
}
return ret;
}
}
//区间修改,单点查询,本质是利用差分的思想。
//其中b[]是a[]的差分数组
public void test() {
binary_indexed_tree2 tree = new binary_indexed_tree2();
for(int i=0;i<n;i++) {
a[i]=in.nextInt();
tree.add(i,a[i]-a[i-1]);
}
//区间修改,比如在(l,r)区间增加d
tree.add(l,d);
tree.add(r+1,-d);
//单点查询x
System.out.println(tree.query(x));
}
public static class binary_indexed_tree2 {
private int n;
private int a[];
private int b[];
public binary_indexed_tree2() {
binary_indexed_tree2(1000);
}
public binary_indexed_tree2(int n) {
a = new int[n];
b = new int[n];
this.n = n;
}
//单点修改
public void add(int x,int d) {
for(int i=x;i>0;i-=lowbit(i)) {
b[i]+=d*(lowbit(i));
}
}
//区间查询
public int change(int x) {
int ret = 0;
for(int i=x;i>=0;i-=lowbit(i)) {
ret += b[i];
}
return ret;
}
}
// 区间查询,区间修改
// 差分数组前n项的前n项和
public static class binary_indexed_tree3 {
private int n;
private int a[];
private int b[];
private int c[];
public binary_indexed_tree2() {
binary_indexed_tree2(1000);
}
public binary_indexed_tree2(int n) {
a = new int[n];
b = new int[n];
this.n = n;
}
public void add(int x,int y,int d) {
add2(x,d,b);
add2(y+1,-d,b)
add2(x,(x-1)*d,c);
add2(y+1,-d*(y),c);
}
public int query(int x,int y) {
int rx = get(x-1,b)*(x-1)-get(x-1,c);
int ry = get(y,b)*y-get(y,c);
return ry-rx;
}
public void add(int x,int d,int []arr) {
for(int i=x;i<=n;i+=lowbit(i))
arr[i]+=d;
}
public int get(int x,int []arr) {
int ret = 0;
for(int i=x;i;i-=lowbit(x)) {
ret +=arr[i];
}
return ret;
}
}
}
以上是关于算法模板之树状数组的主要内容,如果未能解决你的问题,请参考以下文章