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

【一维 前缀和+差分】

一、一维前缀和

1.1 定义

给定一个数组 a[1..n],其前缀和数组 pre[1..n] 定义为:

pre[i]=a[1]+a[2]+⋯+a[i] pre[i] = a[1] + a[2] + \dots + a[i] pre[i]=a[1]+a[2]++a[i]

pre[i] 表示原数组从第 1 项到第 i 项的和。

1.2 构建

int a[N], pre[N];
for (int i = 1; i <= n; i++) 
{pre[i] = pre[i - 1] + a[i];
}

1.3 区间求和

使用前缀和可以在 O(1)O(1)O(1) 时间内求任意区间 [l,r][l, r][l,r] 的和:

sum=pre[r]−pre[l−1] sum = pre[r] - pre[l - 1] sum=pre[r]pre[l1]

1.4 应用场景

  • 快速计算区间和
  • 优化暴力 O(n2)O(n^2)O(n2) 的区间统计问题为 O(n)O(n)O(n)

1.5 示例

// 输入一个数组,求多个区间 [l, r] 的和
int a[N], pre[N];
cin >> n >> q;
for (int i = 1; i <= n; i++) cin >> a[i];
for (int i = 1; i <= n; i++) pre[i] = pre[i - 1] + a[i];while (q--) 
{int l, r;cin >> l >> r;cout << pre[r] - pre[l - 1] << '\n';
}

二、一维差分数组

2.1 定义

对于原数组 a[1..n],其差分数组 diff[1..n] 定义为:

diff[i]=a[i]−a[i−1]  (i≥2),  diff[1]=a[1] diff[i] = a[i] - a[i - 1]\ \ (i \geq 2),\ \ diff[1] = a[1] diff[i]=a[i]a[i1]  (i2),  diff[1]=a[1]

通过差分数组可以快速实现对一个区间 [l,r][l, r][l,r] 的所有值同时加上一个数 ddd

2.2 构建

int a[N], diff[N];
diff[1] = a[1];
for (int i = 2; i <= n; i++) 
{diff[i] = a[i] - a[i - 1];
}

2.3 区间加法操作

若想对区间 [l,r][l, r][l,r] 所有数加上 ddd,只需:

diff[l] += d;
diff[r + 1] -= d;

原理在于:差分数组记录的是“增量”,只需要在区间起点加一个数、在区间终点的下一位减去这个数,就能确保中间所有位置都累加这个值。

然后通过前缀和还原整个数组:

a[1] = diff[1];
for (int i = 2; i <= n; i++) 
{a[i] = a[i - 1] + diff[i];
}

2.4 区间减法操作

若想对区间 [l,r][l, r][l,r] 所有数减去 ddd,也可以使用差分数组:

diff[l] -= d;
diff[r + 1] += d;

原理类似:差分数组记录的是“增量”,如果我们想对一个区间 [l,r][l, r][l,r] 的所有元素减去 ddd,只需要在区间起点加上 −d-dd,在区间终点的下一位加上 +d+d+d,就能确保整个区间内的值都减少 ddd,而其他位置不受影响。这与区间加法操作完全对称,只是将 ddd 替换为 −d-dd

2.5 应用场景

  • 多次区间加操作(比树状数组/线段树更快)
  • 多次构造某种“影响”或“变化”的模型(如教室占用、涨价、染色)

2.6 示例

// 初始数组为 0,对多个区间加值,输出最终数组
int diff[N] = {0};
cin >> n >> m; // n 个元素,m 次操作
for (int i = 1; i <= m; i++) 
{int l, r, d;cin >> l >> r >> d;diff[l] += d;diff[r + 1] -= d;
}// 还原结果数组
int a[N];
a[0] = 0;
for (int i = 1; i <= n; i++) 
{a[i] = a[i - 1] + diff[i];cout << a[i] << ' ';
}

三、前缀和 vs 差分数组

技术优势典型操作使用时机
前缀和快速区间求和查询 [l,r][l,r][l,r] 区间和多次查区间和
差分数组快速区间加区间加 ddd ororor −d-dd多次改区间数值

它们两个往往成对出现,比如:

  • 差分数组批量处理区间修改
  • 再通过前缀和恢复最终值

四、常见问题汇总

  1. 差分数组的还原为什么用前缀和?

    差分数组记录的是相邻元素之间的增量,所以前缀和就是原数组。

  2. 差分数组是否支持区间乘法?

    不支持,差分只能处理区间加减。

  3. 差分数组是否可以从 0 开始?

    可以,但要注意下标对应的意义,最好从 1 开始更清晰。

  4. 是否每次都需要重建差分数组?

    看情况。如果每次操作互不干扰,可以复用;否则建议重建或静态开数组并清空。


五、总结

  • 前缀和用于高效区间查询
  • 差分数组用于高效区间修改
  • 两者配合使用是处理“区间加减 + 查询”类问题的利器

在处理数据量较大的题目(如 10510^510510610^6106)时,前缀和与差分是比线段树更快、更简洁的选择。

http://www.dtcms.com/a/279392.html

相关文章:

  • 互斥锁与同步锁
  • IIS错误:Service Unavailable HTTP Error 503. The service is unavailable.
  • Unity Shader 预热与缓存优化
  • Unity中HumanBodyBones骨骼对照
  • 卡在“pycharm正在创建帮助程序目录”
  • 笔试——Day6
  • 达梦国产数据库安装
  • React Hook 详解:原理、执行顺序与 useEffect 的执行机制
  • 切比雪夫多项式
  • leetcode 1290. 二进制链表转整数 简单
  • C++类模版与友元
  • 进程、线程、协程
  • windows内核研究(进程与线程-进程结构体EPROCESS)
  • Django基础(一)———创建与启动
  • 【反转链表专题】【LeetCode206.反转链表】【LeetCode25.K个一组翻转链表】【LeetCode234.回文链表】
  • Spring Boot 自带的 JavaMail 集成
  • android Perfetto cpu分析教程及案例
  • 5G 到 6G通信技术的革新在哪里?
  • 腾讯云和火山云优劣势对比
  • 电力协议处理框架C++版(三)
  • CA-IS3082W 隔离485 收发器芯片可能存在硬件BUG
  • LTspic下载,帮助及演示电路
  • sfe_py的应力云图计算与显示step by step
  • 暑期自学嵌入式——Day02(C语言阶段)
  • 揭开图像的秘密:OpenCV直方图入门详解
  • 代数基本定理最简短的证明
  • 对于独热编码余弦相似度结果为0和词向量解决了词之间相似性问题的理解
  • ubuntu之坑(十五)——设备树
  • gRPC和http长轮询
  • 新手向:Python自动化办公批量重命名与整理文件系统