前缀和

update 1009睡觉前,更新了多维前缀和和树上前缀和

前缀和

前缀和

定义

前缀和是一种重要的预处理,能大大降低查询的时间复杂度。

可以简单理解为“数列的前(n)项的和”。

实现非常简单。

开两个数组(A[n],B[n])

然后把(A)数组前(n)项累加放入(B)数组。

代码实现:

B[i]=A[i]+B[i-1];

二维/多维前缀和

基于容斥原理

多维前缀和的普通求解方法几乎基于容斥原理(扫雷原理)

比如我们有这样一个矩阵(alpha),可以视为二维数组(借用(OI~ ~WIKI)的数据)。

1 2 4 3
5 1 2 4
6 3 5 9

我们同样定义(sum)

[sum_{x,y}=sum^{x}_{i=1}sum^{y}_{j=1}a_{i,j} ]

那么所求出的二维前缀和矩阵长成:

1  3  7  10
6  9  15 22
12 18 29 45

为了防止有的人(未来回看的我自己)看不懂上面的(sum)式子。

我随便举几个栗子

7=1+2+4

18=1+2+5+1+6+3

这样应该就挺好理解了……吧。

那么显而易见的第一个问题就是通过递推求(sum)的过程。

(sum_{i,j}=sum{i-1,j}+sum_{i,j-1}-sum_{i-1,j-1}+a_{i,j})

background Layer 1 1 2 4 3 5 1 2 4 6 3 5 9

如图所示,显然要减去中间重复的一部分。

第二个问题就是如何应用,求((x1,y1)-(x2,y2))子矩阵的和。

那么,根据类似的思考过程,很容易得到答案(sum_{x2,y2}-sum_{x1-1,y2}-sum_{x2,y1-1}+sum_{x1-1,y1-1})

基于(DP)思想

基于容斥原理计算的方法优点在于形式简单,不需要特别记忆,但当维数升高时,其复杂度较高。

还有一种通过(DP)来计算高维前缀和的方法。

设高维空间(U)共有(N)维,需要对(f[cdot])求高维前缀和(sum[cdot])

(sum[i][state])表示同(state)(D-i)维相同的所有点对于(state)点高维前缀和的贡献。

有定义可知(sum[0][state]=f[state]),以及(sum[state]=sum [D][state])

其递推关系为(sum[i][state]=sum[i-1][state]+sum[i][state']),其中(state')为第(i)维恰好比(state)少1的点。

该方法的时间复杂度为(O(D imes |U|)),其中(|U|)为高维空间(U)的大小。

伪代码实现:

for state
	sum[state]=f[state];
for(i=0;i<=D;i++)
	for 以字典序从小到大枚举state
    	sum[state]+=sum[state'];

树上前缀和

(sum_i)表示结点(i)到根结点的权值总和。

  • 若是边权,(x)(y)路径上的和为(sum_x)+(sum_y)-(2sum_lca)
  • 若是点权,(x)(y)路径上的和为(sum_x)+(sum_y)-(sum_lac)-(sum_{f_{a_{lca}}})

(LCA)的求法参见最近公共祖先

原文地址:https://www.cnblogs.com/JingFenHuanZhe/p/QianZhuiHe1009.html