从二维前缀和的另一种方法谈起
求二维前缀和的常用方法为容斥,但对于高维前缀和,容斥的效率显然是不够优秀的。
因此,我们可以考虑从不同维度来进行转移,每次只转移一个维度。
for (int i=1;i<=n;i++) for (int j=1;j<=n;j++) s[i][j]+=s[i-1][j];
for (int i=1;i<=n;i++) for (int j=1;j<=n;j++) s[i][j]+=s[i][j-1];
如何理解?图上的红色箭头表示第一维的转移,蓝色箭头表示第二维的转移。容易发现,由于我们先后进行了两种颜色箭头的转移,所以对于一个节点,其左上角的所有节点都可以通过向下若干次转移,并向右若干次来到该节点,而其他节点则无法转移至此,因此该算法的正确性可以得到保证。
若推广至
n
n
n 维,只需先枚举维数,再进行转移即可。
适用范围
高维前缀和(基于DP的前缀和)适用于求解类似 ∑ i ⊆ k a i \sum\limits_{i\subseteq k}a_i i⊆k∑ai 的问题,其中求和运算可以改为任意可合并的操作,如 max , min \max,\min max,min 等。
具体问题中,一般会运用二进制数进行状态压缩。
for (int j=0;j<n;j++) // 维数
for (int i=1;i<(1<<n);i++)
if ((i>>j)&1) f[i]+=f[i^(1<<j)];