当前位置: 首页 > news >正文

树状数组及应用

目录

1.树状数组的概念与基本编码

1.1.引导

1.2.lowbit(x)

1.3.树状数组的编码

2.树状数组的基本应用

2.1.单点修改+区间查询

2.2.区间修改+单点查询

例题:

2.3.区间修改+区间查询

例题:


如果数列A是静态不变的,那么处理前缀和复杂度为O(n),查询为O(1),但如果序列是动态变化的,如改变其中一个元素,那么就需要重新计算前缀和,如果每次查询都有变化,那么复杂度会大幅度增加。

有两种数据结构可以高效的处理这个问题:树状数组与线段树。

1.树状数组的概念与基本编码

1.1.引导

如图所示,c[1] = A[1], c[2] = c[1] + A[2], c[3] = A[3], c[4] = c[2] + c[3] + A[4], ... , c[8] = c[4] + c[6] + c[7] + A[8]。

利用c数组可以高效的完成以下两个操作。

(1)查询,即求前缀和sum。
(2)维护,即元素a发生变化时,能以O(log_2(n))的高效率修改c[] 的值。

结论:

(1)查询过程是每次去掉二进制的最后一个1。例如,求sum[7]:

  1. sum[7] += c[7]
  2. 7的二进制是111,去掉最后一个1,得110,即c[6],所以sum[7] += c[6]
  3. 110,去掉最后一个1,得100,sum[7] += c[4]
  4. 100,去掉最后一个1就没有了

故sum[7] = c[7] + c[6] + c[4]

(2)维护的过程是每次在二进制最后的1上加1。例如,更新a[3]:

  1. 3的二进制是11,在最后一个1上加1,得100,所以修改c[4];
  2. 100,在最后一个1上加1,得1000,所以修改c[8];
  3. 继续修改c[16],c[32]...

树状数组的关键就是找到最后一个1。

1.2.lowbit(x)

lowbit(x) = x & (-x),功能为找到x的二进制数最后一个1。其原理是利用负数的补码,例如x = 6 = 000110,(-x)_{} 补 = 111010,那么x & (-x) = 10 = 2;

lowbit(x) 部分结果如下:

x

x的二进制

lowbit(x)

tree[x]数组

1

1

1

tree[1] = a1

2

10

2

tree[2] = a2 + a1

3

11

1

tree[3] = a3

4

100

4

tree[4] = a4 + a3+ a2+ a1

5

101

1

tree[5] = a5

6

110

2

tree[6] = a6 + a5

7

111

1

tree[7] = a7

令m = lowbit(x),tree[x]的值是把a_{x}和他前面共m个数相加的结果。

tree[]数组是通过lowbit计算出的树状数组,它能够以二分的复杂度存储一个数列的数据,具体的说,tree[x]存储的是区间[x - lowbit(x) + 1, x]的每个数的和。

1.3.树状数组的编码

下面给出单点修改+区间查询的代码

#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define lowbit(x) (x & (-x))
const int N = 1000;
int tree[N];
void update(int x, int d) {//单点修改,修改玄素a[x],a[x] = a[x] + dwhile (x <= N) {tree[x] += d;x += lowbit(x);}
}
ll sum(int x) {//查询前缀和:返回前缀和sum = a[1] + a[2] + .., + a[x]ll ans = 0;while (x > 0) {ans += tree[x];x -= lowbit(x);}return ans;
}
void solve() {int n;cin >> n;vector<ll> a(n + 1, 0);//a[0]不用memset(tree, 0, sizeof(tree));for (int i = 1; i <= n; i++) {cin >> a[i];update(i, a[i]);}//查询区间和:cout << "Old : sum([1,n-1]):" << sum(n - 1) - sum(0) << endl;//模拟一次修改,a[n-1] + 100update(n - 1, 100);cout << "New : sum([1,n-1]):" << sum(n - 1) - sum(0) << endl;
}
int main() {ios::sync_with_stdio;cin.tie(0);cout.tie(0);solve();return 0;
}
/*
输入:
10
4 5 6 7 8 9 10 11 12 13
输出:
Old : sum([1,n-1]):72
New : sum([1,n-1]):172
*/

此代码过程:

(1)初始化:先清空数组tree,然后读取a数组每一个元素,用update() 逐步处理这n个数,得到tree[]数组;
(2)求前缀和:用sum()计算,求和基于tree数组;
(3)单点修改:执行update()函数,修改数组tree[]。

2.树状数组的基本应用

2.1.单点修改+区间查询

1.1.3.树状数组的编码已经给出

2.2.区间修改+单点查询

利用差分是前缀和的逆运算来求解

例题:

两种解法:

第一种,单纯的差分数组

#include<bits/stdc++.h>
using namespace std;
int n, a, b, diff[100002];
int main() {ios::sync_with_stdio(false);cin.tie(0);while (cin >> n && n != 0) {for (int i = 0; i <= n; i++) {diff[i] = 0;}for (int i = 0; i < n; i++) {cin >> a >> b;diff[a] += 1;diff[b + 1] -= 1;}diff[1] += diff[0];cout << diff[1];for (int i = 2; i <= n; i++) {diff[i] += diff[i - 1];cout << ' ' << diff[i];}}return 0;
}

 第二种,利用树状数组

#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define lowbit(x) (x & (-x))
const int N = 100010;
int tree[N];
void update(int x, int d) {while (x <= N) {tree[x] += d;x += lowbit(x);}
}
ll sum(int x) {ll ans = 0;while (x > 0) {ans += tree[x];x -= lowbit(x);}return ans;
}
void solve() {int n;while (cin >> n && n != 0) {memset(tree, 0, sizeof(tree));for (int i = 1; i <= n; i++) {int L, R;cin >> L >> R;update(L, 1);update(R + 1, -1);}for (int i = 1; i <= n; i++) {if (i != n)cout << sum(i) << ' ';else cout << sum(i) << endl;}}
}
int main() {ios::sync_with_stdio;cin.tie(0);cout.tie(0);solve();return 0;
}

2.3.区间修改+区间查询

完成区间修改需要一个tree,区间查询也需要一个tree,所以可以利用两个tree达成此要求

a_{1}+a_{2}+...+a_{k - 1 }+a_{k}
=d_{1} + (d_{1}+d_{2}) +... + \sum_{i=1}^{k-1}d_{i}+\sum_{i=1}^{k}d_{i}
=k\sum_{i =1 }^{k}d_{i} - \sum_{i =1 }^{k}(i-1)d_{i}

所以可以分别处理d和(i-1)d两个数组的树状数组

例题:

#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define lowbit(x) (x & (-x))
const int N = 100010;
ll tree1[N], tree2[N];
void update1(ll x, ll d) {while (x <= N) {tree1[x] += d;x += lowbit(x);}
}
ll sum1(ll x) {ll ans = 0;while (x > 0) {ans += tree1[x];x -= lowbit(x);}return ans;
}
void update2(ll x, ll d) {while (x <= N) {tree2[x] += d;x += lowbit(x);}
}
ll sum2(ll x) {ll ans = 0;while (x > 0) {ans += tree2[x];x -= lowbit(x);}return ans;
}
void solve() {ll n, m;memset(tree1, 0, sizeof(tree1));memset(tree2, 0, sizeof(tree2));cin >> n >> m;ll old = 0, a;for (int i = 1; i <= n; i++) {cin >> a;update1(i, a - old);update2(i, (i - 1) * (a - old));old = a;}while (m--) {ll q, L, R, d;cin >> q;if (q == 1) {cin >> L >> R >> d;update1(L, d);update1(R + 1, -d);update2(L, (L - 1) * d);update2(R + 1, -R * d);}else {cin >> L >> R;cout << R * sum1(R) - sum2(R) - (L - 1) * sum1(L - 1) + sum2(L - 1) << endl;}}
}
int main() {ios::sync_with_stdio;cin.tie(0);cout.tie(0);solve();return 0;
}

相关文章:

树状数组及应用

目录 1.树状数组的概念与基本编码 1.1.引导 1.2.lowbit(x) 1.3.树状数组的编码 2.树状数组的基本应用 2.1.单点修改&#xff0b;区间查询 2.2.区间修改单点查询 例题&#xff1a; 2.3.区间修改&#xff0b;区间查询 例题&#xff1a; 如果数列A是静态不变的&#xff…...

HarmonyOS 应用开发案例

本帖下方集中了HarmonyOS Next应用开发时&#xff0c;会遇到的常见应用案例。后续会持续更新大量案例&#xff0c;帮助开发者快速学习。欢迎感兴趣的同学加入Q&#xff1a;454901491 72.手写绘制及保存图片案例&#xff08;0319更新&#xff09;&#xff08;点此查看源码实现&…...

【C++ leetcode】双指针(专题完结)

15. 三数之和 题目 给你一个整数数组 nums &#xff0c;判断是否存在三元组 [nums[i], nums[j], nums[k]] 满足 i ! j、i ! k 且 j ! k &#xff0c;同时还满足 nums[i] nums[j] nums[k] 0 。请 你返回所有和为 0 且不重复的三元组。 注意&#xff1a;答案中不可以包含重复的…...

动态代理大总结

1.开启EnableAspectJAutoProxy注解 @EnableAspectJAutoProxy注解【相当于加了个BeanPostProcessor】,会导入AspectJAutoProxyReqistrar这个类,会把AnnotationAwareAspectJAutoProxyCreator注册进spring容器中,注册进容器后还会看这两个属性的值【proxyTargetClass,exposeP…...

理解Harris角点检测的数学原理

Harris角点检测的数学原理 Harris角点检测基于图像的局部自相似性,它通过分析图像窗口在各个方向上移动时灰度变化的程度来识别角点,它通过计算每个像素点的Harris响应值来评估该点是否为角点。数学上,这种变化可以通过构建一个二次型函数来量化,该函数基于图像在x和y方向上…...

ETIM -国际贸易的产品分类标准

ETIM 是除了XML 国际交流标准BMEcat之外的国际贸易的产品分类标准。 什么是ETIM &#xff1f; ETIM是一种基于分类识别共享和交换产品数据的格式。这种广泛使用的技术产品分类标准是为了构建 B2B 专业人员之间的信息流而制定的。 为什么选择ETIM&#xff1f; ETIM分类模型的开…...

MySQL高阶SQL语句

文章目录 MySQL高阶SQL语句MySQL常用查询1、按关键字排序1.1 语法1.2 ASC和DESC1.3 对数据表中信息进行排序1.3.1 普通排序1.3.2 结合where进行条件过滤1.3.3 对多个字段进行排序 2、区间判断及查询不重复记录2.1 and/or —— 且/或2.1.1 普通查询2.1.2 嵌套/多条件查询 2.2 di…...

聊聊CSS

css 的介绍 学习目标 能够知道css的作用 1. css 的定义 css(Cascading Style Sheet)层叠样式表&#xff0c;它是用来美化页面的一种语言。 没有使用css的效果图 使用css的效果图 2. css 的作用 美化界面, 比如: 设置标签文字大小、颜色、字体加粗等样式。 控制页面布局, 比如…...

C语言 青蛙跳台阶问题

目录 ​编辑 1.问题描述 2.问题分析 3.全部代码 4.结语 1.问题描述 一只青蛙可以一次跳一级台阶&#xff0c;也可以一次跳两级台阶&#xff0c;如果青蛙要跳上n级台阶有多少种跳法&#xff1f; 2.问题分析 当台阶只有一级时&#xff0c;只能跳一级&#xff0c;所以只有一…...

【Django开发】前后端分离美多商城项目第3篇:用户部分,1. 后端接口设计:【附代码文档】

美多商城项目4.0文档完整教程&#xff08;附代码资料&#xff09;主要内容讲述&#xff1a;美多商城&#xff0c;项目准备1.B2B–企业对企业,2.C2C–个人对个人,3.B2C–企业对个人,4.C2B–个人对企业。项目准备&#xff0c;配置1. 修改settings/dev.py 文件中的路径信息,2. INS…...

DHCP snooping、DHCP安全及威胁防范

DHCP snooping、DHCP安全及威胁防范 [SW1]display dhcp snooping user-bind all&#xff0c;查看DHCP snooping表项。 DHCP snooping&#xff1a; 表项是通过服务器发送给客户端的ACK报文生成的。 只能在交换机上开启&#xff0c;路由器不支持&#xff0c;并且建议在接入交…...

用eclipse创建Web项目,通过Servlet实现Web访问的功能。

要使用Eclipse和Tomcat 10创建一个简单的Web项目&#xff0c;并通过Servlet实现Web访问功能&#xff0c;你需要遵循以下详细步骤&#xff1a; 1. 安装和配置Eclipse和Tomcat 10 确保你已经安装了Eclipse IDE for Java EE Developers和Tomcat 10。如果还没有安装&#xff0c;请…...

tools.jar下载 Unable to create schema compiler

网上查找了一堆下载tools.jar的都是忽悠人的&#xff0c;在这我就直接告诉大家&#xff0c;直接在电脑的JDK安装路径下的lib文件下复制就可以了。如果没有的话可以diss我我发给你...

【0278】checkpointer 共享内存(CheckpointerShmem)初始化(3)

0. 关于checkpointer 检查指针是Postgres 9.2的新特性。它处理所有检查点。自上次检查点以来,检查点在经过一定时间后自动分发,并且还可以发出信号来执行请求的检查点。(GUC参数要求每隔这么多WAL段就有一个检查点,这是通过后端在填充WAL段时发出信号来实现的; checkpointer…...

算法打卡day29|贪心算法篇03|Leetcode 1005.K次取反后最大化的数组和、134. 加油站、135. 分发糖果

算法题 Leetcode 1005.K次取反后最大化的数组和 题目链接:1005.K次取反后最大化的数组和 大佬视频讲解&#xff1a;K次取反后最大化的数组和视频讲解 个人思路 思路清晰&#xff0c;因为是取反当然是取越小的负数越好&#xff0c;那么先按绝对值排序。如果是负数就取反&#…...

【hexo博客6】自定义域名 购买、配置、更新部署

【hexo博客6】自定义域名 购买、配置、更新部署 写在最前面自定义域名购买域名DNS配置Github 配置 更新部署博客 &#x1f308;你好呀&#xff01;我是 是Yu欸 &#x1f30c; 2024每日百字篆刻时光&#xff0c;感谢你的陪伴与支持 ~ &#x1f680; 欢迎一起踏上探险之旅&#…...

Django使用pyJwt进行token校验

1.登录成功后返回token&#xff0c;这里使用authenticate进行校验是否存在该用户 def login(request):try:data json.loads(request.body)username data.get(username)password data.get(password)if not all([username, password]):return to_response(status400, msg参数…...

❤️算法笔记❤️-(每日一刷-26、删除有序数组的重复项)

文章目录 题目思路解法 题目 给你一个 非严格递增排列 的数组 nums &#xff0c;请你** 原地** 删除重复出现的元素&#xff0c;使每个元素 只出现一次 &#xff0c;返回删除后数组的新长度。元素的 相对顺序 应该保持 一致 。然后返回 nums 中唯一元素的个数。 考虑 nums 的唯…...

银河麒麟系统安装设备类型选择lvm简单模式之后,数据写入导致失败导致系统重启无法正常加载

银河麒麟系统安装设备类型选择lvm简单模式之后&#xff0c;数据写入导致失败导致系统重启无法正常加载 一 系统环境1.1 系统版本信息1.2 通过镜像安装的过程中选择设备类型选择的是lvm简单模式 二 问题描述三 问题修复过程3.1 挂载ISO镜像&#xff0c;引导到字符终端界面3.2 修…...

Mybatis-核心配置文件 / Mybatis增删改查

1. 核心配置文件 1.1. 概述 核心配置文件是MyBatis框架中用于集中定义全局配置信息的XML文件&#xff0c;其内部包含了一系列预设标签&#xff0c;用于设置数据库连接、对象映射、类型处理等关键参数。这些标签遵循特定的排列顺序&#xff0c;尽管并非所有标签都是强制性的&a…...

国防科技大学计算机基础课程笔记02信息编码

1.机内码和国标码 国标码就是我们非常熟悉的这个GB2312,但是因为都是16进制&#xff0c;因此这个了16进制的数据既可以翻译成为这个机器码&#xff0c;也可以翻译成为这个国标码&#xff0c;所以这个时候很容易会出现这个歧义的情况&#xff1b; 因此&#xff0c;我们的这个国…...

<6>-MySQL表的增删查改

目录 一&#xff0c;create&#xff08;创建表&#xff09; 二&#xff0c;retrieve&#xff08;查询表&#xff09; 1&#xff0c;select列 2&#xff0c;where条件 三&#xff0c;update&#xff08;更新表&#xff09; 四&#xff0c;delete&#xff08;删除表&#xf…...

React Native 开发环境搭建(全平台详解)

React Native 开发环境搭建&#xff08;全平台详解&#xff09; 在开始使用 React Native 开发移动应用之前&#xff0c;正确设置开发环境是至关重要的一步。本文将为你提供一份全面的指南&#xff0c;涵盖 macOS 和 Windows 平台的配置步骤&#xff0c;如何在 Android 和 iOS…...

从零实现富文本编辑器#5-编辑器选区模型的状态结构表达

先前我们总结了浏览器选区模型的交互策略&#xff0c;并且实现了基本的选区操作&#xff0c;还调研了自绘选区的实现。那么相对的&#xff0c;我们还需要设计编辑器的选区表达&#xff0c;也可以称为模型选区。编辑器中应用变更时的操作范围&#xff0c;就是以模型选区为基准来…...

mongodb源码分析session执行handleRequest命令find过程

mongo/transport/service_state_machine.cpp已经分析startSession创建ASIOSession过程&#xff0c;并且验证connection是否超过限制ASIOSession和connection是循环接受客户端命令&#xff0c;把数据流转换成Message&#xff0c;状态转变流程是&#xff1a;State::Created 》 St…...

将对透视变换后的图像使用Otsu进行阈值化,来分离黑色和白色像素。这句话中的Otsu是什么意思?

Otsu 是一种自动阈值化方法&#xff0c;用于将图像分割为前景和背景。它通过最小化图像的类内方差或等价地最大化类间方差来选择最佳阈值。这种方法特别适用于图像的二值化处理&#xff0c;能够自动确定一个阈值&#xff0c;将图像中的像素分为黑色和白色两类。 Otsu 方法的原…...

postgresql|数据库|只读用户的创建和删除(备忘)

CREATE USER read_only WITH PASSWORD 密码 -- 连接到xxx数据库 \c xxx -- 授予对xxx数据库的只读权限 GRANT CONNECT ON DATABASE xxx TO read_only; GRANT USAGE ON SCHEMA public TO read_only; GRANT SELECT ON ALL TABLES IN SCHEMA public TO read_only; GRANT EXECUTE O…...

Qwen3-Embedding-0.6B深度解析:多语言语义检索的轻量级利器

第一章 引言&#xff1a;语义表示的新时代挑战与Qwen3的破局之路 1.1 文本嵌入的核心价值与技术演进 在人工智能领域&#xff0c;文本嵌入技术如同连接自然语言与机器理解的“神经突触”——它将人类语言转化为计算机可计算的语义向量&#xff0c;支撑着搜索引擎、推荐系统、…...

【学习笔记】深入理解Java虚拟机学习笔记——第4章 虚拟机性能监控,故障处理工具

第2章 虚拟机性能监控&#xff0c;故障处理工具 4.1 概述 略 4.2 基础故障处理工具 4.2.1 jps:虚拟机进程状况工具 命令&#xff1a;jps [options] [hostid] 功能&#xff1a;本地虚拟机进程显示进程ID&#xff08;与ps相同&#xff09;&#xff0c;可同时显示主类&#x…...

Python ROS2【机器人中间件框架】 简介

销量过万TEEIS德国护膝夏天用薄款 优惠券冠生园 百花蜂蜜428g 挤压瓶纯蜂蜜巨奇严选 鞋子除臭剂360ml 多芬身体磨砂膏280g健70%-75%酒精消毒棉片湿巾1418cm 80片/袋3袋大包清洁食品用消毒 优惠券AIMORNY52朵红玫瑰永生香皂花同城配送非鲜花七夕情人节生日礼物送女友 热卖妙洁棉…...