AcWing
  • 首页
  • 课程
  • 题库
  • 更多
    • 竞赛
    • 题解
    • 分享
    • 问答
    • 应用
    • 校园
  • 关闭
    历史记录
    清除记录
    猜你想搜
    AcWing热点
  • App
  • 登录/注册

树状数组

作者: 作者的头像   合欢与海棠 ,  2025-07-03 17:02:18 · 江苏 ,  所有人可见 ,  阅读 4


0


树状数组

建立数组$c$,其中$c[x]$保存序列$a$的区间$[x - lowbit(x) + 1, x]$中所有数的和


满足性质:

  1. 每个内部节点$c[x]$保存以它为根的子树中多有叶节点的和
  2. 每个内部节点$c[x]$的子节点的个数等于$lowbit(x)$的位数
  3. 除树根外,每个$c[x]$的父节点是$c[lowbit(x) + x]$
  4. 树的深度为$O(\log N)$

基本操作:

  1. 快速求前缀和$O(\log n)$
// 查询序列a第1-x个数的和,求a[l - r]的和即为ask(r) - ask(l - 1)
int ask(int x)
{
    int ans = 0;
    for (; x; x -= x & -x) ans += c[x];
    return ans;
}
  1. 修改某个数$O(\log n)$
// 给序列中一个数a[x]加上y
void add(int x, int y)
{
    for (; x <= N; x += x & -x) c[x] += y;
}

建树方式:
1. $O(n \log n)$方式,每次$add(i, a[i])$
2. $O(n)$方式

// 方式1
void build() 
{
    for (int i = 1; i <= n; i++) 
    {
        tr[i] += a[i];

        // 获得父节点下标
        int fa = i + lowbit(i); 
        // 判断父节点是否超出数列范围
        if (fa <= n) tr[fa] += tr[i];
    }
}
// 方式2
c[x] = s[x] - s[x - lowbit(x)]

拓展基本操作:

将原数组改用差分数组加入到树状数组

  1. 修改区间值$O(\log n)$
区间[l, r]都加d
add(l, d), add(r + 1, -d);
  1. 查询某个数$O(\log n)$ ask(x)

0 评论

App 内打开
你确定删除吗?
1024
x

© 2018-2025 AcWing 版权所有  |  京ICP备2021015969号-2
用户协议  |  隐私政策  |  常见问题  |  联系我们
AcWing
请输入登录信息
更多登录方式: 微信图标 qq图标 qq图标
请输入绑定的邮箱地址
请输入注册信息