A-1:树状数组

A-1:树状数组

  • 1.介绍
    • Q1:树状数组解决什么问题?
    • Q2:树状数组的使用
      • 1.前置知识:lowbit(x)
      • 2.单点修改
      • 3.求[1,n]的和
      • 4.区间查询
      • 5.hh
    • Q3:树状数组是否优化了
    • Q4:上图上例子解释上面说的东西(Important)
  • 2.习题练习

1.介绍

树状数组是一个比较难以理解的高级数据结构(至少我觉得很难😢)

由于难以理解,所以只好从以下几个方面去理解:

  1. 树状数组用于解决什么问题
  2. 如何去使用树状数组
  3. 树状数组是否优化了算法
  4. 用例子说明

新手不要去死钻“树状数组怎么被总结出来的?树状数组的发明过程”,如果有完美的回答感谢给个链接我去圆梦一下😢

!!对于这个学习,我的看法是先知道什么是树状数组,怎么写,然后根据数据和画图走几遍过程,然后做题。最后再去看数学推导(如果时间充裕的话)。

Q1:树状数组解决什么问题?

预告:数状数组解决”单点修改,区间查询(当然区间也可以是一个点)“问题

首先前缀和是大家都知道的基础算法。假设前缀和数组是 p r e [ n ] pre[n] pre[n],原数组是 a [ n ] a[n] a[n]
p r e [ i ] 表示数组区间 [ 0 , i ] 之和 = a [ 0 ] + a [ 1 ] + a [ 2 ] + . . . + a [ i ] pre[i]表示数组区间[0,i]之和=a[0]+a[1]+a[2]+...+a[i] pre[i]表示数组区间[0,i]之和=a[0]+a[1]+a[2]+...+a[i]
查询区间的时间复杂度是 O ( 1 ) O(1) O(1),比如: 查询 [ i , j ] [i,j] [i,j]之和= p r e [ j ] − p r e [ i − 1 ] = a [ i ] + a [ i + 1 ] + . . . + a [ j ] pre[j]-pre[i-1]=a[i]+a[i+1]+...+a[j] pre[j]pre[i1]=a[i]+a[i+1]+...+a[j],很显然只需要一次操作即可。
重点来了!! 如果修改原数组的一个元素,假设 a [ 0 ] = a [ 0 ] + 1 a[0]=a[0]+1 a[0]=a[0]+1,那么需要 p r e [ 0 ] + 1 pre[0]+1 pre[0]+1 p r e [ 1 ] + 1 pre[1]+1 pre[1]+1 p r e [ n ] + 1 pre[n]+1 pre[n]+1
总结发现,每次修改一个原数组元素,当前元素到数组末尾的所有元素的前缀和都需要改变,那么维护前缀和的时间复杂度是 O ( n ) O(n) O(n),树状数组就是优化掉这个O(n)的大杀器!

总结一下:数状数组解决”单点修改,区间查询(当然区间也可以是一个点)“问题

Q2:树状数组的使用

😱😱😱😱😱

1.前置知识:lowbit(x)

l o w b i t ( x ) lowbit(x) lowbit(x),找x最低位的1及1右边(比1更低位)的所有数的总和,当然最低位1右边全是0

x的十进制数x的二进制数lowbit(x)(换成十进制)
1010102
1110111
1211004
1311011
1411102
1511111
160001 000016

现在应该是了解lowbit做一个什么事情,那么如何实现呢?

void lowbit(x)
{
	return x&(-x);
}

对的,就是这么简单
对数取负表现为 ”除最高位,其余位取反,最低位加1”
来翻译一下: 令x=10
x=1010
-x=1110
x&(-x)=0010

Perfect😋。

2.单点修改

不同于前缀和数组,修改一个点,需要修改O(n)次前缀和区间,而树状数组只需要修改O( log ⁡ 2 n \log_2 n log2n)次
操作为

void add(int i, int y)  //单点修改(同时可以初始化C数组)
{
	for(;i<=n;i+=lowbit(i))
	{
	    C[i]+=y;
	}
}

3.求[1,n]的和

不同于前缀和O(1)次,查询前n个数的和需要O( log ⁡ 2 n \log_2 n log2n)次
操作为

int sum(int i)  //前缀和,求[1,i]的和
{
    int res=0;
	for(;i>0;i-=lowbit(i))
	    res+=C[i];
	return res;
}

4.区间查询

操作为

int Query(int i,int j)  //查询[1,j]区间和
{
	return sum(i)-sum(j-1);
}

5.hh

很显然,已经给出了单点修改,区间查询的操作,且时间复杂度实实在在更低更有效,比单纯使用前缀和好很多。那么有这些知识就可以去写题了。

Q3:树状数组是否优化了

和前缀和相比:

前缀和树状数组
区间查询O(1)O( log ⁡ 2 n \log_2 n log2n)
单点修改O(n)O( log ⁡ 2 n \log_2 n log2n)

当n非常大的时候
1 + n > 2 ∗ ( log ⁡ 2 n ) 1+n>2 *(\log_2 n) 1+n>2(log2n)

Q4:上图上例子解释上面说的东西(Important)

在这里插入图片描述
这个图是 借的,嗯,肯定是借的。
别被误导了!!,C数组不是前缀和,C[4]不是前4个数之和,这个数组单独看没有意义,只有和函数配合使用才有意义!!

现在先抛出问题:需要对数组进行单点修改,区间查询。

现在有数组 A [ 1 ] . . . A [ 8 ] = 1 , 2 , 3 , 4 , 5 , 6 , 7 , 8 A[1]... A[8]={1,2,3,4,5,6,7,8} A[1]...A[8]=1,2,3,4,5,6,7,8
先初始化树状数组C,这个数组单独不代表什么,要和其它操作一起才有意义

void add(int i, int y)  //单点修改(同时可以初始化C数组)
{
	for(;i<=n;i+=lowbit(i))
	{
	    C[i]+=y;
	}
}
C[i]+=yi+=lowbit(i),C[i]+=yi+=lowbit(i) ,C[i]+=yi+=lowbit(i),C[i]+=y
C[1]+=1C[2]+=1C[4]+=1C[8]+=1
C[2]+=2C[4]+=2C[8]+=2
C[3]+=3C[4]+=3C[8]+=3
C[4]+=4C[8]+=4
C[5]+=5C[6]+=5C[8]+=5
C[6]+=6C[8]+=6
C[7]+=7C[8]+=7
C[8]+=8
iC[i]
11
23
33
410
55
611
77
836

这就是初始化树状数组,那么先来看查询。
查询 (对照上面的表看,自己琢磨一下)

int sum(int i)  //前缀和,求[1,i]的和
{
    int res=0;
	for(;i>0;i-=lowbit(i))
	    res+=C[i];
	return res;
}
isum(i)
1res=C[1]=1
2res=C[2]=3
3res=C[3]+C[2]=6
7res=C[7]+C[6]+C[4]=28
8res=C[8]=36

2.习题练习

给个链接,兄弟们去刷吧😋
洛谷树状数组题集
Leetcode树状数组题集

洛谷的先做题集里面的模板题

稍后把我的题解搬几个过来。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/560829.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Oracle体系结构初探:聊聊REDO

上一篇文章写了undo&#xff08;文章链接&#xff1a;聊聊UNDO&#xff09;&#xff0c;这篇和大家一起聊聊redo。redo如果按照我的傻瓜翻译&#xff0c;意为再次去做、重新去做。Oracle官方对于redo的描述是&#xff1a;记录对数据所做的所有更改&#xff0c;包括未提交和已提…

Electron+Vue3整合 - 开发时状态整合

说明 本文介绍一下 Electron Vue3 的整合的基本操作。实现的效果是 &#xff1a; 1、一个正常的Vue3项目&#xff1b; 2、整合加入 Electron 框架 &#xff1a;开发时 Electron 加载的是开发的vue项目&#xff1b;步骤一&#xff1a;创建vue3项目 常规操作&#xff0c;不再赘…

启动 UE4编辑器报 加载 Plugin 失败

启动 UE4编辑器报 加载 Plugin 失败&#xff0c;报如下错误&#xff1a; Plugin ‘SteamVR’ failer to load because module ‘SteamVR’ could not be found. Please ensure the plugin is properly installed, otherwise consider disabling the plugin for this project. …

yolov5-6.0调测记录

直接运行yolov5-6.0/detect.py&#xff0c;输出如下&#xff1a; image 1/2 C:\Users\dun\Downloads\yolov5-6.0\data\images\bus.jpg: 640x480 4 persons, 1 bus, Done. (0.216s) image 2/2 C:\Users\dun\Downloads\yolov5-6.0\data\images\zidane.jpg: 384x640 2 persons, 2…

单链表的简单应用

目录 一、顺序表的问题及思考 二、链表的概念及结构 三、单链表的实现 3.1 增 3.1.1 尾插 3.1.2 头插 3.1.3 指定位置前插入 3.1.4 指定位置后插入 3.2 删 3.2.1 尾删 3.2.2 头删 3.2.3 指定位置删除 3.2.4 指定位置后删除 3.2.5 链表的销毁 3.3 查 3.4 改 四…

【Godot4自学手册】第三十九节利用shader(着色器)给游戏添加一层雾气效果

今天&#xff0c;主要是利用shader给游戏给地宫场景添加一层雾气效果&#xff0c;增加一下气氛&#xff0c;先看一下效果&#xff1a; 一、新建ParallaxBackground根节点 新建场景&#xff0c;根节点选择ParallaxBackground&#xff0c;命名为Fog&#xff0c;然后将该场景保…

什么是AIoT?

什么是AIoT? AIoT&#xff0c;即人工智能物联网&#xff0c;是一种将人工智能&#xff08;AI&#xff09;技术与物联网&#xff08;IoT&#xff09;相结合的新型应用形态。它不仅实现了设备之间的互联互通&#xff0c;还赋予了它们更智能化的特性。AIoT的核心在于通过AI的数据…

prometheus+grafana可视化监控

prometheus监控 一、用二进制安装 1、安装Prometheus 打开官方网址:https://prometheus.io/download/ wget https://github.com/prometheus/prometheus/releases/download/v2.45.4/prometheus-2.45.4.linux-amd64.tar.gz下载完成后解压一下安装包 tar vxf prometheus-2.45.…

解锁棋盘之谜:探索N皇后问题的全方位解决策略【python 力扣51题】

作者介绍&#xff1a;10年大厂数据\经营分析经验&#xff0c;现任大厂数据部门负责人。 会一些的技术&#xff1a;数据分析、算法、SQL、大数据相关、python 欢迎加入社区&#xff1a;码上找工作 作者专栏每日更新&#xff1a; LeetCode解锁1000题: 打怪升级之旅 python数据分析…

软考138-上午题-【软件工程】-软件评审

一、软件评审 通常&#xff0c;把“质量”理解为“用户满意程度”。为了使得用户满意&#xff0c;有以下两个必要条件&#xff1a; (1) 设计的规格说明书符合用户的要求&#xff0c;这称为设计质量。 (2) 程序按照设计规格说明所规定的情况正确执行&#xff0c;这称为程序质…

Docker安装教程,什么系统都有

下载Docker 如果你的系统是图形界面的&#xff0c;比如windows、mac、ubuntu等&#xff0c;到 Docker 官网下载 Docker Desktop。 官网链接: https://www.docker.com/products/docker-desktop/ 根据你的系统选择对应的安装包&#xff0c;然后下载&#xff0c;是不是特别简单&a…

Git TortoiseGit 安装使用详细教程

前言 Git 是一个免费的开源分布式版本控制系统&#xff0c;是用来保存工程源代码历史状态的命令行工具&#xff0c;旨在处理从小型到非常大型的项目&#xff0c;速度快、效率高。《请查阅Git详细说明》。TortoiseGit 是 Git 的 Windows Shell 界面工具&#xff0c;基于 Tortoi…

改进前后端交互实例

前后端交互实例(javaweb05)-CSDN博客 在这之前我假设大家都已经学完了IOC和DI 不明白的这里我也解释一下,首先是两个概念 1.控制反转:对象的创建控制权由程序自身转到外部(容器) 2.依赖注入:容器为程序提供运行时所依赖的资源 Bean对象:IOC容器中创建,关联的对象,称之为be…

【wpf】ObservableCollection 跨线程报错问题

背景 ObservableCollection 我们之前介绍过他和List的区别。ObservableCollection 的好处在于&#xff0c;当集合发生变化时&#xff0c;能发送通知通知界面发生相应的更改。但是ObservableCollection 有个弊端。无法在非UI线程中访问。 要么就是通知失效了&#xff0c;要么就…

从0到1实现RPC | 接入Apollo配置中心

一、代码实现 添加依赖 添加apollo客户端的依赖和spring配置相关依赖 添加监听器 通过实现ApplicationContextAware接口&#xff0c;获取Spring上下文。 使用ApolloConfigChangeListener注解监听命名空间rpc-demo-provider.yaml和默认的application.properties。 监听逻辑…

前端页面助手 (vue)

快速开发页面&#xff08;图形化开发页面&#xff09; 自主编辑 然后自己也可以修改属性 最后导出页面即可 github地址 ;https://github.com/opentiny/tiny-engine

虹科Pico汽车示波器 | 免拆诊断案例 | 2016款保时捷911 GT3 RS车发动机异响

一、故障现象 一辆2016款保时捷911 GT3 RS车&#xff0c;搭载4.0 L水平对置发动机&#xff08;型号为MA176&#xff09;&#xff0c;累计行驶里程约为4.2万km。车主反映&#xff0c;1星期前上过赛道&#xff0c;现在发动机有“哒哒”异响。 二、故障诊断 接车后试车&#xff…

C++语言·类和对象(下)

1. 初始化列表 我们回忆上节写的MyQueue类&#xff0c;其中有两个栈类和一个int类型&#xff0c;栈类因为其特殊性&#xff0c;要开空间&#xff0c;所以我们必须手搓Stack类的构造函数。但是正常来说MyQueue自动生成的构造函数会调用自定义类型的默认构造函数&#xff0c;也就…

Proxy 代理

意图 为其它对象提供一种代理以控制这个对象的访问。 结构 Proxy保存一个引用使得代理可以访问实体&#xff1b;提供一个与Subject的接口相同的接口&#xff0c;使代理可以用来替代实体&#xff1b;控制实体的存取&#xff0c;并可能负责创建和删除它&#xff1b;其他功能依赖…

【leetcode面试经典150题】63. 删除链表的倒数第 N 个结点(C++)

【leetcode面试经典150题】专栏系列将为准备暑期实习生以及秋招的同学们提高在面试时的经典面试算法题的思路和想法。本专栏将以一题多解和精简算法思路为主&#xff0c;题解使用C语言。&#xff08;若有使用其他语言的同学也可了解题解思路&#xff0c;本质上语法内容一致&…