【树状数组】讲解

一.介绍

 树状数组(Fenwick Tree),也称为二叉索引树(Binary Indexed Tree,BIT),是一种用于高效处理动态数组前缀和的数据结构。它可以在O(log n)的时间复杂度内完成单点更新和区间查询操作。

树状数组的主要应用是计算数组的前缀和。它通过将数组元素按照二进制表示的索引进行组织,使得每个节点存储一定范围内的元素的和。通过利用二进制的特性,树状数组可以高效地进行更新和查询操作。

树状数组的基本操作包括:

  1. 单点更新(Update):将指定位置的元素值增加或减少一个给定的增量。
  2. 区间查询(Query):计算指定区间内的元素和。

树状数组的构建过程如下:

  1. 初始化一个长度为n的数组,并将所有元素初始化为0。
  2. 对于每个位置i,将原始数组中的元素依次加到树状数组中,同时更新相关节点的值。

树状数组的更新操作可以通过不断将当前位置的索引加上其最低位的1来实现。查询操作可以通过不断将当前位置的索引减去其最低位的1来实现。

树状数组的优点是实现简单、空间效率高,并且支持高效的单点更新和区间查询操作。它在解决一些与前缀和相关的问题时非常有用,比如计算逆序对、求解逆序数等。

 


二.详细讲解

(1)建树

若我们原数组为{1,2,3,4,5,6,7,8,9};

我们不妨可以这样加快区间合计算速度。

 

当我们求:

c[1-9]=c[1-8]+c[9]

c[1-8]=c[1-8]

c[1-7]=c[1-4]+[5-6]+c[7]

c[1-6]=c[1-4]+c[5-6]

c[1-5]=c[1-4]+c[5] 

.........

这样的话我们修改一个单值,只需要再修改它的父节点即可。

但我们再仔细看看会发现在求c[1-?]数组时都不需要用到右子树。

因为是奇数,加上即可,是偶数直接是父节点,根本不需要右子树。我们优化掉。

于是树就是这样了:

 

一棵树没了右子树,自然节点就从O(n)-->O(logn);

只也就算修改值只需要O(logn)的由来。

(2)建立/修改c数组

我们可以实现树了,这里就可以用代码来实现。

因为是树,所以可以使用二进制辅助。

一个父节点有多少左子节点呢?其实就是它数组下标值的位权值。

位权值就是x&(-x)求得。

 

位权值就是c数组包含的原数组元素的个数。

所以c[8]有a数组的8个元素,即: c[8]=a[1]+a[2]+a[3]+a[4]+a[5]+a[6]+a[7]+a[8];

所以c[6]有a数组的2个元素,即: a[5]+a[6];

总结:c[x]有a数组的(x&(-x))个元素,即:c[x]= a[x-lowbit(x)+1]+....+a[x];

注意的是修改就要一次修改彻底,所以添加/修改就要修改它所以的父节点

一个数x,它的父节点就是x+=(x&(-x));

修改元素的函数如下:

void update(int x,int y){ //下标 && 值 for(;x<=n;x+=(x&(-x))) {c[x]+=y;}
}

(3)查询区间

查询区间其实就是修改区间的逆运算。

就是累加它的子节点,查询函数为:

int fun(int x){  //return [1,x]int ans=0;while(x){ans+=c[x];x-=(x&(-x));}return ans;
}

 但这只能查询1-x啊,x-y怎么办?

求fun(y)-fun(x-1)不就行了嘛。

即a[3-8]=a[1-8]-a[1-2];


三.模板题

P3374 【模板】树状数组 1 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)

题目描述:

有n个整数,可能会有两种操作: 1.将某一个数加上x;2.求出某区间数的和。
输入要求第一行包含两个整数N、M,分别表示该数列数字的个数和操作的总个数。第二行包含N个用空格分隔的整数,其中第i个数字表示数列第i项的初始值。
接下来M行每行包含3个整数,表示一个操作,具体如下:

操作1: 格式:1x k,将第x个数加上k格式:2xy

操作2:输出区间[x,y]内每个数的和

样例输入:

5 5

1 5 4 2 3

1 1 3

2 2 5

1 3 -1

1 4 2

2 1 4

样例输出:

14 

16

 


四 .参考代码

#include<bits/stdc++.h>
#define maxn 500005
using namespace std;
int n,m;
int a[maxn];  //原数组 
int c[maxn];  //树状树状 
void update(int x,int y){ //下标 && 值 for(;x<=n;x+=(x&(-x))) {c[x]+=y;}
}
int fun(int x){  //return [1,x]int ans=0;while(x){ans+=c[x];x-=(x&(-x));}return ans;
}
int main(){scanf("%d%d",&n,&m);for(int i=1;i<=n;i++){cin>>a[i];update(i,a[i]); //建立树状数组 } while(m--){int op,x,y;scanf("%d%d%d",&op,&x,&y);if(op==1){update(x,y);}else{ //[3,7]=[1,7]-[1,2]cout<<fun(y)-fun(x-1)<<endl;}}return 0;
} 

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

C# Blazor 学习笔记(3):路由管理

文章目录 前言路由管理App.razor设置登录页面设置空布局 前言 我们知道使用Blazor的官方模板&#xff0c;我们会自动得到一个拥有侧边栏的布局页面。但是我们发现我们所有新建的页面都有侧边栏。有时候我们需要跳出这个布局&#xff0c;比如我要做登录页面的时候&#xff0c;我…

微信小程序中的全局数据共享(状态管理)使用介绍

开发工具&#xff1a;微信开发者工具Stable 1.06 一、状态管理简介 微信小程序全局状态是指可以在不同页面之间共享的数据或状态。 它可以存储用户的登录状态、个人信息、全局配置信息等。 二、安装MobX 1、安装NPM 在资源管理器的空白地方点右键&#xff0c;选择“在外部…

css在线代码生成器

这里收集了许多有意思的css效果在线代码生成器适合每一位前端开发者 布局&#xff0c;效果类&#xff1a; 网格生成器https://cssgrid-generator.netlify.app/ CSS Grid Generator可帮助开发人员使用CSS Grid创建复杂的网格布局。网格布局是创建Web页面的灵活和响应式设计的强…

解密HTTP代理爬虫中的IP代理选择与管理策略

在当今数据驱动的世界中&#xff0c;HTTP代理爬虫作为一项重要的数据采集工具&#xff0c;其成功与否往往取决于IP代理的选择与管理策略。作为一家专业的HTTP代理产品供应商&#xff0c;我们深知IP代理在数据采集中的重要性。在本文中&#xff0c;我们将分享一些关于HTTP代理爬…

如何使用 ChatGPT 为 Midjourney 或 DALL-E 等 AI 图片生成提示词

人工智能为创意产业开辟了一个充满可能性的全新世界。人工智能最令人兴奋的应用之一是生成独特且原创的艺术品。Midjourney 和 DALL-E 是人工智能生成艺术的两个突出例子&#xff0c;吸引了艺术家和艺术爱好者的注意。在本文中&#xff0c;我们将探索如何使用 ChatGPT 生成 AI …

某科技公司提前批测试岗

文章目录 题目 今天给大家带来一家提前批测试岗的真题&#xff0c;目前已经发offer 题目 1.自我介绍 2.登录页面测试用例设计 3.如何模拟多用户登录 可以使用Jmeter,loadRunner性能测试工具来模拟大量用户登录操作去观察一些参数变化 4.有使用过Jmeter,loadRunner做过性能压…

Jmeter组件作用域及执行顺序

目录 一、Jmeter八大可执行元件 二、组件执行顺序 三、组件作用域 四、特殊说明 一、Jmeter八大可执行元件 配置元件---Config Element 用于初始化默认值和变量&#xff0c;以便后续采样器使用。配置元件大其作用域的初始阶段处理&#xff0c;配置元件仅对其所在的测试树分…

数学知识(一)

一、数论 1.1质数 定义:在所有大于1的自然数&#xff0c;如果只包含1和本身这两个约数&#xff0c;就被称为质数(素数). 质数的判断:试除法 bool is_prime(int n) {if(n < 2) return false;for(int i 2;i < n / i;i ){if(n % i 0)return false;}return true; } 分…

【LangChain】向量存储(Vector stores)

LangChain学习文档 【LangChain】向量存储(Vector stores)【LangChain】向量存储之FAISS 概要 存储和搜索非结构化数据的最常见方法之一是嵌入它并存储生成的嵌入向量&#xff0c;然后在查询时嵌入非结构化查询并检索与嵌入查询“最相似”的嵌入向量。向量存储负责存储嵌入数…

数据泄露的平均成本创历史新高

IBM Security 发布了年度数据泄露成本报告&#xff0c;显示数据泄露的全球平均成本在 2023 年达到 445 万美元&#xff0c;创下该报告的历史新高&#xff0c;并且比过去 3 年增加了 15%。 检测和升级成本在同一时间段内跃升了 42%&#xff0c;占违规成本的最高部分&#xff0c…

无涯教程-Lua - 垃圾回收

Lua使用自动内存管理&#xff0c;该管理使用基于Lua内置的某些算法的垃圾回收。 垃圾收集器暂停 垃圾收集器暂停用于控制垃圾收集器之前需要等待多长时间&#xff1b; Lua的自动内存管理再次调用它。值小于100意味着Lua将不等待下一个周期。同样&#xff0c;此值的较高值将导…

使用socket实现UDP版的回显服务器

文章目录 1. Socket简介2. DatagramSocket3. DatagramPacket4. InetSocketAddress5. 实现UDP版的回显服务器 1. Socket简介 Socket&#xff08;Java套接字&#xff09;是Java编程语言提供的一组类和接口&#xff0c;用于实现网络通信。它基于Socket编程接口&#xff0c;提供了…

opencv36-形态学操作-膨胀 cv2.dilate()

膨胀操作是形态学中另外一种基本的操作。膨胀操作和腐蚀操作的作用是相反的&#xff0c;膨胀操作能对图像的边界进行扩张。膨胀操作将与当前对象&#xff08;前景&#xff09;接触到的背景点合并到当前对象内&#xff0c;从而实现将图像的边界点向外扩张。如果图像内两个对象的…

分布式应用:ELFK集群部署

目录 一、理论 1.ELFK集群 2.filebeat 3.部署ELK集群 二、实验 1. ELFK集群部署 三、总结 一、理论 1.ELFK集群 &#xff08;1&#xff09;概念 ELFK集群部署&#xff08;FilebeatELK&#xff09;&#xff0c;ELFK ES logstashfilebeatkibana 。 数据流 架构 2.fi…

零基础C#编写上位机如何入门?

想要学习C#编写上位机&#xff0c;需要具备以下基础知识&#xff1a; C#编程语言基础.NET框架的使用WinForm窗体应用程序开发技术基本的数据结构和算法知识 为了方便理解&#xff0c;我将为您列出一些入门步骤&#xff1a; 学习C#基础语法和.NET框架&#xff0c;掌握基本编程…

【Ajax】笔记-JQuery发送jsonp请求

前端 <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width, initial-scale1.0"><title>jQuery-jsonp</title><style>#re…

python+opencv实现显示摄像头,截取相关图片,录取相关视频

实时显示摄像头图像 按下空格键&#xff0c;截取图片 按下tab键&#xff0c;开始录制摄像内容&#xff0c;再次按下&#xff0c;结束录制 按下Esc键&#xff0c;关闭窗口 import cv2 import numpy#第几章图片 img_count0InitVideoFalse #第几个视频 video_count0 video_flagFa…

【Linux 网络】 传输层协议之TCP协议 TCP的三次握手和四次挥手

TCP协议 TCP协议段格式谈谈什么是 “可靠” 和 “不可靠”TCP协议段——序号与确认序号TCP协议段——窗口大小TCP协议段 —— 六个标志位确认应答机制&#xff08;ACK&#xff09;超时重传机制连接管理机制TCP 的三次握手四次挥手TCP三次握手四次挥手总结图 滑动窗口流量控制拥…

将Visio和Excel导出成没有白边的PDF文件

1、VISIO如何无白边导出pdf格式 在使用Latex时&#xff0c;要导入矢量图eps格式。但是VISIO无法输出eps格式&#xff0c;这就需要将其导出为pdf。但是导出pdf时&#xff0c;往往会有大量的白边。VISIO无白边导出pdf格式的方法如下&#xff1a; 1.文件——开发工具——显示sha…

OpenLayers入门,OpenLayers解析通过fetch请求的GeoJson格式数据,并叠加要素文字标注,以行政区划边界为例

专栏目录: OpenLayers入门教程汇总目录 前言 本章讲解如何使用OpenLayers通过fetch请求geojson数据,然后通过OpenLayers解析为Feature要素叠加到图层上,并且通过动态设置标注方式显示要素属性为文字标注。 本章还是以行政区划边界为例,这个示例在开发中比较常用,建议收藏…