树状数组:
一、概念:树状数组(Binary Indexed Trees,简称,BIT)是一种特殊的数据结构,这种数据结构的时空复杂度和线段树相似,但是它的系数要小得多。它可以方便地查询出一段区间中的数字之和。其查询和修改的时间复杂度均为O(logN),并且是一个在线的数据结构,可以随时修改并查询。我接下来用一道题目来介绍树状数组的几个基本操作。
二、应用:
- 区间求和类问题(前缀和)
- 求序列中第 K 大数
- “图腾”类问题的统计
- 最大值/最小值
三、模板代码:
1、区间求和类型:
#include<bits/stdc++.h>
#include<cmath>
#define mem(a,b) memset(a,b,sizeof a);
#define INF 0x3f3f3f3f
using namespace std;
typedef long long ll;
const int maxn=200010;
int n,m;
int a[maxn], rs[maxn];
int lowbit(int x)
{
return x & -x;
}
void update_sum(int x,int val)
{
while(x<=n)
{
rs[x]+=val;
x+=lowbit(x);
}
}
int query_sum(int x)
{
int res=0;
while(x>0)
{
res+=rs[x];
x-=lowbit(x);
}
return res;
}
int main()
{
while(~scanf("%d%d",&n,&m))
{
mem(rs,0);
for(int i=1;i<=n;i++)
{
scanf("%d",&a[i]);
update_sum(i,a[i]);
}
char ch[5];
int l,r;
while(m--)
{
scanf("%s%d%d",ch,&l,&r);
if(ch[0]=='Q') printf("%d\n",query_sum(r)-query_sum(l));
else update_sum(l,r);
}
}
return 0;
}
2、最值类型:点击打开链接
四、解析(附图):
1、主要理解了“x+=lowbit(x)” 和 “x-=lowbit(x)” 和 “x--”(有些代码中是 "r--") 这三个理解了是在做什么即可,直接看图。
“x+=lowbit(x)”:访问直系父结点,比如:C[1]点开始,则会访问:C[1] --> C[2] --> C[4] --> C[8]。
“x-=lowbit(x)”:访问同一辈的左兄弟结点,比如:C[7]点开始,则会访问:C[7] --> C[6] --> C[4] --> End。
“x--”:访问左子结点,比如:C[6]点开始,则会访问:C[6] --> C[5]。
Ps:如果有时题目需要,还需要继续访问的话,需要 C[x-1] 操作,比如:访问到 C[4] 结束时,想继续访问,则需要下个从 C[3] 开始,依此类推。
2、至于利用二进制为什么这么巧妙可以得出第1点这个规律,其实我也不知道,数学就是这么神奇~