【算法 高级数据结构】树状数组:一种高效的数据结构(二)

🚀个人主页:为梦而生~ 关注我一起学习吧!
💡专栏:算法题、 基础算法、数据结构~赶紧来学算法吧
💡往期推荐
【算法基础 & 数学】快速幂求逆元(逆元、扩展欧几里得定理、小费马定理)
【算法基础】深搜
数据结构各内部排序算法总结对比及动图演示(插入排序、冒泡和快速排序、选择排序、堆排序、归并排序和基数排序等)
【算法 & 高级数据结构】树状数组:一种高效的数据结构(一)

上一篇文章我们介绍了树状数组这个数据结构,并且进行了其原理的数学推导,这篇文章基于上一篇文章,来讲一下这个数据结构在算法题中的应用

还不知道树状数组是什么的来看这篇文章:【算法 & 高级数据结构】树状数组:一种高效的数据结构(一)

题目来源:AcWing


文章目录

  • 0 通用模板
  • 1 单点修改,区间求和
  • 2 区间增减,单点查询
  • 3 区间增减,区间求和


0 通用模板

首先,通用模板先摆上

//lowbit
int lowbit(int x){return x & -x;
}//修改操作
void add(int x, int c){for(int i = x; i <= n; i += lowbit(i)) tr[i] += c;
}//查询操作
int sum(int x){int res = 0;for(int i = x; i; i -= lowbit(i)) res += tr[i];return res;
}

1 单点修改,区间求和

  • 例题
    在这里插入图片描述

输入格式
第一行一个数 n n n

第二行是 n n n
个数,分别代表 y 1 , y 2 , … , y n y_1,y_2,…,y_n y1y2,,yn

输出格式
两个数,中间用空格隔开,依次为 V 的个数和 的个数。

数据范围
对于所有数据, n ≤ 200000 n≤200000 n200000,且输出答案不会超过 int64。
y 1 ∼ y n y_1∼y_n y1yn 1 1 1 n n n 的一个排列。

输入样例

5
1 5 3 2 4

输出样例

3 4
  • 主要思路

因为两个符号的特点对应的每个点的纵坐标有这样的特点: V 意味着两边点的纵坐标高于当前点的纵坐标, 意味着两边的纵坐标小于当前的纵坐标。所以我们只需要遍历两次数组,记录每个点左右高于或低于当前点的纵坐标的点的数量,然后利用排列组合,计算出总数。

以下题解来源:https://www.acwing.com/solution/content/13818/

  1. 从左向右依次遍历每个数a[i],使用树状数组统计在i位置之前所有比a[i]大的数的个数、以及比a[i]小的数的个数。
    统计完成后,将a[i]加入到树状数组。
  2. 从右向左依次遍历每个数a[i],使用树状数组统计在i位置之后所有比a[i]大的数的个数、以及比a[i]小的数的个数。
    统计完成后,将a[i]加入到树状数组。
  • 代码
#include<iostream>
#include<algorithm>
#include<cstring>
using namespace std;typedef long long LL;const int N = 200010;
int n;
int a[N], tr[N];
int Greater[N], Lower[N];int lowbit(int x){return x & -x;
}//修改操作
void add(int x, int c){for(int i = x; i <= n; i += lowbit(i)) tr[i] += c;
}//查询操作
int sum(int x){int res = 0;for(int i = x; i; i -= lowbit(i)) res += tr[i];return res;
}int main(){cin >> n;for(int i = 1; i <= n; i++) scanf("%d", &a[i]);//将区间分成n份,看每一份左边有多少个大于它和小于它的for(int i = 1; i <= n; i++){int y = a[i];Greater[i] = sum(n) - sum(y);Lower[i] = sum(y - 1);add(y, 1);}//memset一下tr数组,倒着求每一份右边有多少个小于和大于它的memset(tr, 0, sizeof(tr));LL res1 = 0, res2 = 0;for(int i = n; i; i--){int y = a[i];res1 += Greater[i] * (LL)(sum(n) - sum(y));res2 += Lower[i] * (LL)sum(y - 1);add(y, 1);}cout << res1 << " " << res2 << endl;return 0;
}

2 区间增减,单点查询

主要思想:建立差分数组

  • 例题

在这里插入图片描述
数据范围
1 ≤ N , M ≤ 1 0 5 , 1≤N,M≤10^5, 1N,M105,
∣ d ∣ ≤ 10000 , |d|≤10000, d10000,
∣ A [ i ] ∣ ≤ 1 0 9 |A[i]|≤10^9 A[i]109

输入样例

10 5
1 2 3 4 5 6 7 8 9 10
Q 4
Q 1
Q 2
C 1 6 3
Q 2

输出样例

4
1
2
5
  • 主要思路

树状数组每次修改对应的是某个范围的前缀和的值的修改,所以如果需要在大数据量的情况下进行区间修改操作,大概率会TLE的。

但是我们想到,区间操作我们可以利用最基础的差分,使得区间操作优化成 O ( 1 ) O(1) O(1)的复杂度。

可以看到,将题目在原始组上的操作,转换到差分数组上,和树状数组解决的问题一致。

  • 代码
#include<iostream>
#include<algorithm>
using namespace std;typedef long long LL;const int N = 100010;
int tr[N], a[N];
int n, m;int lowbit(int x){return x & -x;
}void add(int x, int c){for(int i = x; i <= n; i += lowbit(i)) tr[i] += c;
}LL quary(int x){LL 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];add(i, a[i] - a[i - 1]);}while(m--){char op;cin >> op;if(op == 'C'){int l, r, d;cin >> l >> r >> d;add(l, d), add(r + 1, -d);}else{int x;cin >> x;cout << quary(x)<< endl;}}return 0;
}

3 区间增减,区间求和

主要思想:建立差分数组+公式

  • 例题

在这里插入图片描述
数据范围
1 ≤ N , M ≤ 1 0 5 , 1≤N,M≤10^5, 1N,M105,
∣ d ∣ ≤ 10000 , |d|≤10000, d10000,
∣ A [ i ] ∣ ≤ 1 0 9 |A[i]|≤10^9 A[i]109

输入样例

10 5
1 2 3 4 5 6 7 8 9 10
Q 4 4
Q 1 10
Q 2 4
C 3 6 3
Q 2 4

输出样例

4
55
9
15
  • 主要思想

上一个应用虽然利用差分数组解决了区间操作的问题,但是区间操作完之后,利用差分数组不利于进行区间查询,所以需要进行一些推导,看看有什么性质可以利用。

数学推导见如下题解:https://www.acwing.com/solution/content/44886/
因此只需维护两个树状数组即可
一个是差分数组d[i]的树状数组tr[i],还有一个是i*d[i]的树状数组tri[i]

  • 代码
#include<iostream>
#include<algorithm>
using namespace std;typedef long long LL;const int N = 100010;
int a[N];   
LL tr1[N], tr2[N];  //tr1[i] : b[i]的前缀和  tr2[i] : i * b[i]的前缀和
int n, m;int lowbit(int x){return x & -x;
}void add(LL tr[], int x, LL c){for(int i = x; i <= n; i += lowbit(i)) tr[i] += c;
}LL quary(LL tr[], int x){LL res = 0;for(int i = x; i; i -= lowbit(i)) res += tr[i];return res;
}LL prefix_sum(int x){return quary(tr1, x) * (LL)(x + 1) - quary(tr2, x);
}int main(){cin >> n >> m;for(int i = 1; i <= n; i++){cin >> a[i];int b = a[i] - a[i - 1];add(tr1, i, (LL)b);add(tr2, i, (LL)i * b);}while(m--){char op;cin >> op;if(op == 'C'){int l, r, d;cin >> l >> r >> d;add(tr1, l, (LL)d), add(tr1, r + 1, (LL)-d);add(tr2, l, (LL)l * d), add(tr2, r + 1, (LL)(r + 1) * -d);}else{int l, r;cin >> l >> r;cout << prefix_sum(r) - prefix_sum(l - 1) << endl;}}return 0;
}

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

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

相关文章

RTthread如何引入webclient和cjson来编写自己的模块代码||SecureCRT的安装与激活||安装VScode

目录 1.RTthread如何引入webclient和cjson来编写自己的模块代码 2.SecureCRT的安装与激活 3.static与const的区别 4.安装VScode 1.RTthread如何引入webclient和cjson来编写自己的模块代码 以我自己的工程为例&#xff1a; 首先将新引入的模块在applicatons下新建cpeinfo文件…

【MySQL】一条 SQL 查询语句在数据库中的执行流程 | SQL语句中各个关键字的执行顺序

创作不易&#xff0c;本篇文章如果帮助到了你&#xff0c;还请点赞 关注支持一下♡>&#x16966;<)!! 主页专栏有更多知识&#xff0c;如有疑问欢迎大家指正讨论&#xff0c;共同进步&#xff01; 给大家跳段街舞感谢支持&#xff01;ጿ ኈ ቼ ዽ ጿ ኈ ቼ ዽ ጿ ኈ ቼ …

知识图表示学习中的负抽样研究综述

摘要 知识图表示学习(KGRL)或知识图嵌入(KGE)在知识构建和信息探索的人工智能应用中起着至关重要的作用。这些模型旨在将知识图中的实体和关系编码到低维向量空间中。在KGE模型的训练过程中&#xff0c;使用正样本和负样本是区分的必要条件。然而&#xff0c;直接从现有的知识…

鸿蒙NXET实战:高德地图定位SDK【获取Key+获取定位数据】(二)

如何申请key 1、创建新应用 进入[控制台]&#xff0c;创建一个新应用。如果您之前已经创建过应用&#xff0c;可直接跳过这个步骤。 2、添加新Key 在创建的应用上点击"添加新Key"按钮&#xff0c;在弹出的对话框中&#xff0c;依次&#xff1a;输入应用名名称&…

Muduo类详解之EventLoop

最核⼼的部分就是 EventLoop 、 Channel 以及 Poller 三个类&#xff0c;其中 EventLoop 可以看作是对业务线程的封装&#xff0c;⽽ Channel 可以看作是对每个已经建⽴连接的封装&#xff08;即 accept(3) 返回的⽂件描述符&#xff09; EventLoop class EventLoop { p…

解决SLF4J: Class path contains multiple SLF4J bindings.

JDK版本&#xff1a;jdk17 IDEA版本&#xff1a;IntelliJ IDEA 2022.1.3 SpringBoot 版本&#xff1a;v2.5.7 maven版本&#xff1a;3.6.3 文章目录 问题描述&#xff1a;原因分析&#xff1a;解决方案&#xff1a;参考资料&#xff1a; 问题描述&#xff1a; 当SpringBoot项目…

并发VS并行

参考文章 面试必考的&#xff1a;并发和并行有什么区别&#xff1f; 并发&#xff1a;一个人同时做多件事&#xff08;射击游戏队友抢装备&#xff09; 并行&#xff1a;多人同时处理同一件事&#xff08;射击游戏敌人同时射击对方&#xff09;

学习数据结构:算法的时间复杂度和空间复杂度

一、算法的复杂度 衡量一个算法的好坏&#xff0c;一般是从时间和空间两个维度来衡量的&#xff0c;即时间复杂度和空间复杂度。 时间复杂度主要衡量一个算法的运行快慢&#xff0c;而空间复杂度主要衡量一个算法运行所需要的额外空间。 算法的时间复杂度 算法中的基本操作的…

SAP BAS中Fiori开发的高阶功能(storyboard, navigation, guided development, variant)

1. 前言 在之前的几篇文章中&#xff0c;我介绍了SAP BAS的一些基本功能&#xff0c;包括账户申请&#xff0c;创建工作区&#xff0c;git的使用以及如何step-by-step去创建出你的第一个Fiori项目等等。在本篇中&#xff0c;我将进一步介绍一些在开发Fiori应用程序时会用到的高…

JAVA学习笔记19(面向对象编程)

1.面向对象编程 1.1 类与对象 1.类与对象的概念 ​ *对象[属性]/[行为] ​ *语法 class cat {String name;int age; }main() {//cat1就是一个对象//创建一只猫Cat cat1 new Cat();//给猫的属性赋值cat1.name "123";cat1.age 10; }​ *类是抽象的&#xff0c;…

前端使用正则表达式进行校验

一、定义 设计思想是用一种描述性的语言定义一个规则&#xff0c;凡是符合规则的字符串&#xff0c;我们就认为它“匹配”了&#xff0c;否则&#xff0c;该字符串就是不合法的。 在 JavaScript中&#xff0c;正则表达式也是对象&#xff0c;构建正则表达式有两种方式&#x…

【可用Claude Opus模型】Claude3国内镜像站,亲测完全超越GPT-4(可用Claude Opus,官网价值20刀)

#今天在知乎看到一个问题&#xff1a;“平民不参与内测的话没有账号还有机会使用Claude 3吗&#xff1f;” 从去年GPT大火到现在&#xff0c;关于GPT的消息铺天盖地&#xff0c;真要有心想要去用&#xff0c;途径很多&#xff0c;别的不说&#xff0c;国内GPT的镜像站到处都是…

探索LLaMA模型:架构创新与Transformer模型的进化之路

引言 在人工智能和自然语言处理领域&#xff0c;预训练语言模型的发展一直在引领着前沿科技的进步。Meta AI&#xff08;前身为Facebook&#xff09;在2023年2月推出的LLaMA&#xff08;Large Language Model Meta AI&#xff09;模型引起了广泛关注。LLaMA模型以其独特的架构…

视频批量爬虫下载工具|可导出视频分享链接|抖音视频提取软件

便捷的视频批量爬虫软件操作指南 抖音视频下载界面图解 主要功能&#xff1a; 关键词批量提取视频和单独视频提取&#xff0c;提取后下载功能。 功能解析&#xff1a; 1. 关键词批量采集视频的解析 对特定关键词进行搜索和视频提取&#xff0c;例如输入“汽车配件”&#x…

2024年洗地机综合实力排行榜:谁才是真正的洗地神器?

近年来&#xff0c;洗地机在行业里&#xff0c;它集合了扫地和拖地以及自动清洁和除菌的功能&#xff0c;备受人们的喜爱&#xff0c;尤其是平时忙于工作并没有多少时间清洁家务的用户&#xff0c;但是对于第一次接触洗地机的用户来说&#xff0c;怎么选购洗地机也是个问题&…

初识React(一)从井字棋游戏开始

写在前面&#xff1a; 磨磨唧唧了好久终于下定决心开始学react&#xff0c;刚刚接触感觉有点无从下脚...新的语法新的格式跟vue就像两种物种...倒是很好奇路由和store是怎么实现的了~v~&#xff0c;一点一点来吧&#xff01;&#xff01;&#xff01; (一)创建项目 使用vite…

蓝桥杯算法 - DP

上一篇&#xff1a;[[蓝桥杯算法-排序、递归、全排列]] 动态规划&#xff08;dp&#xff09; dp即动态规划&#xff0c;常用于&#xff1a;数学&#xff0c;计算机科学&#xff0c;管理学&#xff0c;经济和生物信息学。 dp在生活中也很常见&#xff0c;如&#xff1a;你今天…

今天聊聊Docker

在数字化时代&#xff0c;软件应用的开发和部署变得越来越复杂。环境配置、依赖管理、版本控制等问题给开发者带来了不小的挑战。而Docker作为一种容器化技术&#xff0c;正以其独特的优势成为解决这些问题的利器。本文将介绍Docker的基本概念、优势以及应用场景&#xff0c;帮…

1.4.2 练习

一、颠倒三角形 题目&#xff1a;修改顶点着色器让三角形上下颠倒 更改顶点着色器代码如下&#xff1a; #version 330 corelayout (location 0) in vec3 aPos; //位置变量的属性位置值为0 layout (location 1) in vec3 aColor; //颜色变量的属性位置值为1out vec3 ourColo…

项目配置之道:优化Scrapy参数提升爬虫效率

前言 在当今信息时代&#xff0c;数据是无处不在且无比重要的资源。为了获取有效数据&#xff0c;网络爬虫成为了一项至关重要的技术。Scrapy作为Python中最强大的网络爬虫框架之一&#xff0c;提供了丰富的功能和灵活的操作&#xff0c;让数据采集变得高效而简单。本文将以爬…