考前复习——树状数组
树状数组是一种支持 单点修改 和 区间查询 的,代码量小的数据结构。
什么是「单点修改」和「区间查询」?
假设有这样一道题:
已知一个数列 a,你需要进行下面两种操作:
给定 x, y,将 a[x] 自增 y。
给定 l, r,求解 a[l...r] 的和。
其中第一种操作就是「单点修改」,第二种操作就是「区间查询」。
点击查看代码
int n;
int a[N],c[N];//a[]:原数组 c[]:树状数组
inline int lowbit(int x)//返回最低位1 即树状数组c[]所代表的区间长度
{
return x&(-x);
}
int query(int u)
{
//a[1..u]之和
int ans=0;
for(int i=u;i>0;i-=lowbit(i))
ans+=c[i];
return ans;//请务必记得这个!!!
}
inline int interval(int l,int r)//区间和
{
return query(r)-query(l-1);
}
void single_update(int u,int w)
{
//单点修改:将u位置的值加上w
//修改被a[u]影响的所有的c[]
for(int i=0;i<=u;i+=lowbit(i))
c[i]+=w;
}
int main()
{
cin>>n;//输入节点数
for(int i=1;i<=n;i++)
{
cin>>a[i];
single_update(i,a[i]);//制作c[]
}
cout<<interval(1,n)<<endl;//输出1~n区间和
return 0;
}
若为矩阵 有如下代码
点击查看代码
void add(int x, int y, int v) {
for (int i = x; i <= n ;i += lowbit(i)) {
for (int j = y; j <= m; j += lowbit(j)) {
// 注意这里必须得建循环变量,不能像一维数组一样直接 while (x <= n) 了
c[i][j] += v;
}
}
}
int sum(int x, int y) {
int res = 0;
for (int i = x; i > 0; i -= lowbit(i)) {
for (int j = y; j > 0; j -= lowbit(j)) {
res += c[i][j];
}
}
return res;
}
int ask(int x1, int y1, int x2, int y2) {
// 查询子矩阵和
return sum(x2, y2) - sum(x2, y1 - 1) - sum(x1 - 1, y2) + sum(x1 - 1, y1 - 1);
}
本文来自博客园,作者:pig_pig,转载请注明原文链接:https://www.cnblogs.com/pigAlg/p/17478302.html
浙公网安备 33010602011771号