版权声明:转载记得标明出处哦~ https://blog.csdn.net/weixin_43890047/article/details/88830614
运用到的数学思想:
一
假设现在有一个原数组a(假设a[0] = 0),有一个数组d,d[i] = a[i] - a[i-1],那么
a[i] = d[1] + d[2] + … + d[i]
d数组就是差分数组
所以求a[i]就可以用树状数组维护d[i]的前缀和
即维护的是d[i]的树状数组
上面的数学思想可以实现区间修改,以及单点查询。
下附上代码:
区间修改(1~n)
void change(int x,int k)
{
for (;x <= n;x += lowbit(x)) c[x] += k;
}
{
change(l,x); ///记得要change两次,一个在l,一个在r+1
change(r+1,-x);
}
单点查询
void change(int x,int k)
int getsum(int x) ///得出的就是区间点的值
{
int ans = 0;
for (;x;x -= lowbit(x)) ans += c[x];
return ans;
}
二
根据上面的差分数组的定义可以得到:
a[1] + a[2] + a[3] + … + a[k] = d[1] + d[1] + d[2] + d[1] + d[2] + d[3] + … + d[1] +
d[2] + d[3] + … + d[k] = Σ(k - i + 1) * d[i] (i从1到k)
变化一下 Σa[i] (i从1到k) = Σ(k+1) * d[i] - i * d[i] (i从1到k)
d[i]可以用一个前缀和维护,i * d[i]也可以用一个前缀和进行维护,所以区间修
改,区间查询就变得很方便了
假设c1维护d[i]的前缀和,c2维护d[i] * i的前缀和
区间查询及区间修改
#include<bits/stdc++.h>
using namespace std;
int lowbit(int x)
{
return x&(-x);
}
int getsum(int x)
{
int ans1 = 0;
int ans2 = 0;
for (int i = x;i;i -= lowbit(i))
{
ans1 += (x + 1) * c1[i];
ans2 += c2[i];
}
return ans1 - ans2;
}
void add(int x,int y)
{
for (int i = x;i <= n;i += lowbit(i)) c1[i] += y,c2[i] += x * y;
}
{
add(l,x); //在l处加相应的x,在r+1减去x
add(r+1,-x);
}
现附上参考博文:树状数组区间修改,区间更新:差分数组的运用
基本照搬其文,不过现在时间一晚,不便修改,在此结篇。
题目: 习题:木桩涂涂看