差分树状数组

运用到的数学思想:

假设现在有一个原数组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 v) {for (int i = x;i <= n;i += lowbit(i)) c1[i] += v,c2[i] += x * v;}
{
    add(l,v);           //在l处加相应的x,在r+1减去x
    add(r+1,-v);
}

现附上参考博文:树状数组区间修改,区间更新:差分数组的运用

基本照搬其文,不过现在时间一晚,不便修改,在此结篇。

题目: 习题:木桩涂涂看

所以树状数组可分为两类,一类是差分数组,另一类是前缀和数组


4.24更新此博。贴上的区间查询修改树状数组貌似不能区间赋值,只能区间加减。

  • 2
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值