前缀和简析

news/2024/11/18 5:31:30/文章来源:https://www.cnblogs.com/guozhetao/p/18293114

前缀和

前置知识:$\sum_{i = 1}^{r}{a_i} = a_l + a_{l + 1} + \dots + a_{r - 1} + a_r$
考虑以下数组:

$i$ $1$ $2$ $3$
$a_I$ $3$ $5$ $7$

如果我们要查询 $\sum_{i = 1}^{2}{a_i}$,很显然可以得到 $\sum_{i = 1}^{2}{a_i} = 3 + 5 = 8$。如果我们要查询 $\sum_{i = l}^{r}{a_i}$,则每次的时间复杂度为 $O(r -l)$。
如果我们对于一个长度为 $n$ 的数组查询 $k$ 次(不修改),则时间复杂度为 $O(nk)$ 。如果给定一个 $n = 10^7,k = 10^6$,我们要如何让程序在 1s 内运行完呢?

$i$ $1$ $2$ $3$
$a_I$ $3$ $5$ $7$
$b_I$ $3$ $8$ $15$

我们构造$b_0 = 0,b_i = b_{i - 1} + a_i$,同上表,倘若我们只考虑快速查询 $\sum_{i = 1}^{r}{a_i}$,显而易见原式即为 $\sum_{i = 1}^{r}{a_i} = b_i$,而 $b$ 数组可以在$O(n)$ 的时间范围内预处理完。简易证明见下:

$b_i = b_{i - 1} + a_i = b_{i - 2} + a_{i - 1} + a_i = \sum_{i = 1}^{r}{a_i}$

假如我们转换一下思路,可以发现 $\sum_{i = l}^{r}{a_i} = \sum_{i = 1}^{r}{a_i} - \sum_{i = 1}^{l-1}{a_i} = b_r - b_{l - 1}$,那么我们将单次查询复杂度降到了 $O(1)$,总时间复杂度变为 $O(n + k)$。
在这里插入图片描述
例题

#include<iostream>
#include<cstdio>
#include<cmath>
#include<string>
#include<queue>
#include<map>
#include<algorithm>using namespace std;// 快读
inline int read() {int x = 0,f = 1;char ch = getchar();while (ch < '0' or ch > '9'){if (ch == '-') f = -1;ch = getchar();}while (ch >= '0' and ch <='9'){x = x * 10 + ch - 48;ch = getchar();}return x * f;
}
//快写
inline void write(int x) {if(x < 0) putchar('-'),x = -x;if(x > 9) write(x / 10);putchar(x % 10 + '0');return;
}
//输出char
void writec(char x) {putchar(x);return;
}
int main() {int n = read(),a[100005],m;for(int i = 1;i <= n;i++) a[i] = read() + a[i - 1];m = read();while(m--) {int l = read() - 1,r = read();write(a[r] - a[l]),writec('\n');}return 0;
}

差分

考虑完不修改多次查询,如果我们多次将区间内的所有数加上一个值,最后统一查询,那么会怎么样呢?
假设我们操作2次,第一次让 $a_1 \dots a_3 \gets(a_1 + 3)\dots (a_3+3)$,第二次让 $a_1 ,a_2 \gets(a_1 + 2)\dots (a_2+2)$

$i$ $1$ $2$ $3$
原数组 $3$ $5$ $7$
操作一次 $6$ $8$ $10$
操作两次 $8$ $10$ $10$

如果你对这一些规律不太敏感的话,可以考虑 $b_i = a_i - a_{i - 1}$,那么:

$i$ $1$ $2$ $3$
原$b_i$数组 $3$ $2$ $2$
操作一次 $6$ $2$ $2$
操作两次 $8$ $2$ $0$

显而易见,如果区间加减,$b_i$ 只会改变两个值,切规律如下:

$b_l \gets b_l + k,b_{r + 1} \gets b_{r + 1}- k$。

我们将每次修改由 $O(n)$ 变成了 $O(1)$。

在这里插入图片描述
例题

代码

#include<iostream>
#include<cstdio>
#include<cmath>
#include<string>
#include<queue>
#include<map>using namespace std;
int x[10005];
// 快读
inline int read()
{int x = 0,f = 1;char ch = getchar();while (ch < '0' or ch > '9'){if (ch == '-') f = -1;ch = getchar();}while (ch >= '0' and ch<='9'){x = x * 10 + ch - 48;ch = getchar();}return x * f;
}
//快写
inline void write(int x) {if(x < 0) putchar('-'),x = -x;if(x > 9) write(x / 10);putchar(x % 10 + '0');return;
}
//输出char
void writec(char x) {putchar(x);return;
}
int main() {int t = read();while(t--) {int n = read(),u = read();for(int i = 0;i < n;i++) x[i] = 0;while(u--) {int l = read(),r = read(),val = read();x[l] += val;x[r + 1] -= val;}for(int i = 1;i < n;i++) x[i] += x[i - 1];int q = read();while(q--) {int i = read();write(x[i]),writec('\n');}}return 0;
}

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

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

相关文章

推挽输出和开漏输出

一、推挽输出 1.1推挽输出的概念 推挽(push-pull)输出是由两个MOS或者三极管组成,两个管子始终保持一个导通,另一个截止的状态。当输入高电平时,叫做推;上管Q1导通,下管Q2关闭;电流走向VCC→Q1→Vout。当输入低电平时,叫做挽;上管Q1关闭,下管Q2导通;电流走向Vout→…

数据血缘系列(3)—— 数据血缘可视化之美

大家好,我是独孤风。在当今数据驱动的商业环境中,数据治理成为企业成功的关键因素之一,而数据血缘正是数据治理成功的一个关键。 本文我们详细探讨下数据血缘可视化是什么,该如何实现。并顺便对比一下Apache Atlas 、Datahub、Openmetadata、Marquez、SQLLineage、Amundsen…

进度报告3

(1)1.学习Scanner来用键盘输入数据并写出实例代码并运行成功2.分支与循环结构,与c语言差不多3.Random来生成随机数用Random的案例:猜数字游戏4.数组(2)继续往后学习

防火防盗防CDN流量盗刷

没想到自己的小破站也逃不掉被攻击的命,分分钟就给我刷欠费了。本来不想写这篇文章的,但看到好多大佬(小林coding、 JavaGuide)近期cdn都被盗刷了。 还是来提醒下大家,防火防盗防cdn流量盗刷 事故时间:2024年7月5日晚8点左右 事故现场:好不容易到了周五,想着第二天就周…

记内存条硬件损坏蓝屏的 dump 文件分析

本文记录我的电脑的内存条的硬件损坏了,导致用着用着就蓝屏,我通过启动和故障恢复配置自动蓝屏打 dump 的功能,在蓝屏时创建了 dump 文件。通过分析 dump 文件大概猜测是内存的问题以下是我用 windbg 分析的两次蓝屏 第一次是用着 VS 的过程蓝屏了,我发现好多次都是使用 VS…

.NET 9 预览版 5 发布

微软在6月发布了.NET 9预览版的第五个版本。这个新版本的框架预计将在今年晚些时候正式发布,它是一个标准支持(STS)版本,将在2024年11月12日至2026年5月12日期间在多个操作系统上获得18个月的支持。这个预览版带来了性能改进和一些新特性,例如增强的AI能力、优先级无界通道…

EasyExcel当导出的文件内容为空时,报错excel无法打开xxxx,因为文件格式或扩展名无效,请确定文件未损坏

问题 EasyExcel 导出打开提示"Excel 无法打开文件 xxxxx.xlsx ,因为文件格式或文件扩展名无效 请确定文件未损坏,并且文件扩展名与文件的格式匹 排查 发现是在mysql查询完要导出的数据后,判断查询内容是否有值,如果有的话才进行excelWriter.write(dataList, writeSheet)…

读人工智能全传08人工智能的今天

读人工智能全传08人工智能的今天1. 人工智能的今天 1.1. 未来,或许有些领域会有非常明显的人工智能痕迹,有些领域则不会 1.2. 2018年,来自计算机视觉处理器公司英伟达的研究人员证明了人工智能软件能够创造出虚假的人物照片,并且能够完全令人相信它是…

Java CompletableFuture因在上下文中使用共享变量,导致线程安全问题

背景 在使用CompletableFuture.supplyAsync()时,多个异步中,同时共用的一个查询对象参数,而且在这多个任务中间会穿插地对这个对象进行更改,出现的现象就是可能会导致最终get()结果不符合我们的预期。最终调整方案就是在每个任务supplyAsync()之前单独赋予一个新的final对象…

MySQL中修改一个数据库下包含有某个相同字段的所有表的字段长度

背景 由于业务场景导致某个字段如phone_name涉及到表比较多,目前很多表都有冗余这个字段,但是前期给的字段长度只有varchar(100),不满足目前的需要了,需要把所有的表的字段长度都增大到varchar(255),如果手动一个个修改的话,那么有几百张表,很花时间,所有想到如下办法,…

领取serv00免费虚拟主机

参考 ‍ 教程地址【免费serv00虚拟机SSH登录搭建网站】 ‍ 领取地址 ​​ 领到了 ​​ 登录成功 ​​ 放放上自己的静态网站 ​​ ‍ soulio.serv00.net 缺点:网站的URL中含有中文就会404。权限很少,改不了服务器配置。如果是nginx就好了,nginx支持中文路径。 ​​ URL全英文…

新版mac配置多版本JDK切换和maven套件

新版mac配置多版本JDK和maven套件 新版本的macOS Sonoma系统配置多版本的JDK和Maven开发套件。有平时开发和学习用到的JDK是不同版本的需求,就直接安装多个版本的JDK,使用的时候直接命令进行对应版本的切换,要做到切换JDK版本,可以自己配置并在终端切换,或者使用java的版本…