Basic Thought / Data Structure: 前缀和 Prefix Sum
作者:互联网
在OI中,前缀和是一个重要的优化思想
Function: 求静态区间和
模板题:输入序列\(a_{1..n}\),对于每一个输入的二元组\((l,r)\),求\(\sum_{i=l}^ra_i\)
先想一想朴素算法怎么做吧
对于输入的每一组\((l,r)\),遍历序列\(a_{l..r}\)求和,代码如下
int s(0);
for(int i(l);i<=r;++i)s+=a[i];
return s;
Time complexity: \(O(n)\)
Memory complexity: \(O(1)\)
如果有m次询问,则总时间复杂度\(O(nm)\)
观察这个过程,可以发现有大量多余运算,比如说,对于两次询问,它们区间的交集就是被多余运算的
那么有没有方法使得计算量减少呢?
可以发现\(\sum_{i=l}^ra_i=\sum_{i=1}^ra_i-\sum_{i=1}^{l-1}a_i\)
也就是说如果存在数组\(s_{1..n}\)使得\(s_i=\sum_{j=1}^ia_j\),则
\(\sum_{i=l}^ra_i=s_r-s_{l-1}\)
\(s_{1..n}\)就是传说中的前缀和数组啦!
Operation:
First: 将普通数组\(a_{1..n}\)构造成前缀和数组\(s_{1..n}\)
Second: 对于输入区间\([l,r]\),直接计算出区间和\(s_r-s_{l-1}\)
关键就是前缀和数组如何构造
使用递推思想
\(s_i=\sum_{j-1}^ia_j=\sum_{j-1}^{i-1}a_j+a_i=s_{i-1}+a_i\)
代码如下
求\(s_{1..n}\)
for(int i(1);i<=n;++i)s[i]=s[i-1]+a[i];
询问
return s[r]-s[l-1];
到此为止前缀和的所有基本操作都讲完啦!
Conclusion & Extension:
前缀和是一种泛用性很高的数据结构,也是非常重要的优化思想
它利用预处理和递推的方法减少多余运算,达到优化的目的,被广泛运用于dp的优化中
不仅适用于加法,还适用于所有满足于结合律而且具有单位(对于加法就是0)和逆元(a的逆元是-a)的二元运算,如乘法
但是对于求最值就不太靠谱了(对于这类问题(称为RMQ问题)也有很棒的算法)
前缀和思想的强大产物:树状数组
Particularly, 前缀和还有逆运算,叫差分
到此为止本篇文章就圆满结束啦,请各位奆佬们多多指教和支持,THX!
标签:前缀,..,int,Sum,Thought,Prefix,ra,数组,sum 来源: https://www.cnblogs.com/BrianPeng/p/12165425.html