算法提高课:树状数组

本文介绍了树状数组的基本原理,包括快速求前缀和、修改单个数以及树状数组的建立方式。通过扩展+差分和+公式,解释了如何进行区间操作。文章通过多个例题,如楼兰图腾、一个简单的整数问题和谜一样的牛,展示了树状数组在解决实际问题中的应用,如区间求和。总结中强调了树状数组的核心概念,并提供了直观的二进制理解方式。
摘要由CSDN通过智能技术生成

基本原理

应用:
快速求前缀和
修改某一个数
在这里插入图片描述
分成最多logx个部分,算1-x总和的时候,在加logn个数就可以求出来,复杂度O(logn)
2 ^ i1 是x的二进制表示的最后一位1
在这里插入图片描述
在这里插入图片描述
c[x]表示以x为右端点,长度lowbit的区间内所有数的和

在这里插入图片描述
图中C12应为C9-C12.

所有C的关系如图:
在这里插入图片描述
x> 0, 必然存在最后一位1
x = ----- 100…0, 0 y有k个
Cx = 以x结尾,长度为2^k的区间和
找到x的所有子节点
x-1每一次去掉一个最后的1,去地道k次、
如何通过子节点找父节点
在这里插入图片描述
树状数组的建立方式,关于优化时间负责度的(不是很明白)

扩展 +差分、+公式

在这里插入图片描述
参考差分

令b[n]为a[n]的差分数组,将[L, R] +c 等价于b[l] += c, b[r + 1] -= c;

例题

楼兰图腾

将V最下面那个点的横坐标分成n类
在这里插入图片描述
对于yk,统计有多少处于1——k-1、有多少大于yk,处于k+1 —— n的大于yk,相乘
greater[k].
与之对应的lower[k], 表示的是小于yk的相乘

一个简单的整数问题

维护差分数组

#include <iostream>
#include <cstring>
#include <algorithm>

using namespace std;
const int N = 100010;
typedef long long LL;

int a[N], m, n, l, r, d;
LL tr[N];
char op[2];
int lowbit(int x)
{
   
    return x & -x;
}

void update(int x, int c)  // 位置x加c
{
   
    for (int i = x; i <= n; i += lowbit(i)) tr[i] += c;
}

LL query(int x)  // 返回前x个数的和
{
   
    int res = 0;
    for (int i = x; i; i -= lowbit(i)) res += tr[i];
    return res;
}

int main()
{
   
    cin >> n >> m;
    for (int i = 1; i <= n; i ++ )
    {
   
        cin >> a[i];
    }
    for (int i = 1; i <= n; i ++ )
    {
   
        update(i, a[i] - a[i - 1]);//把a数组转化成差分数组
    }
    while (m -- )
    
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值