背景:
全挂,
卡线没进。
看了师兄们的游记,发现一些好东西没学。
正题:
先考虑容斥的做法。
一维的做法:
for(int i=1;i<=n;i++)
sum[i]=sum[i-1]+a[i];
二维的做法:
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
sum[i][j]=sum[i-1][j]+sum[i][j-1]-sum[i-1][j-1]+a[i][j];
三维的做法:
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
for(int k=1;k<=q;k++)
sum[i][j][k]=sum[i-1][j][k]+sum[i][j-1][k]+sum[i][j][k-1]
-sum[i-1][j-1][k]-sum[i-1][j][k-1]-sum[i][j-1][k-1]
+sum[i-1][j-1][k-1]+a[i][j][k];
假设维数为
。
如此的时间复杂度是
的。
很不优秀啊。
其实有更好的做法。
一维的做法:
for(int i=1;i<=n;i++)
a[i]+=a[i-1];
二维的做法:
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
a[i][j]+=a[i-1][j];
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
a[i][j]+=a[i][j-1];
三维的做法:
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
for(int k=1;k<=q;k++)
a[i][j][k]+=a[i-1][j][k];
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
for(int k=1;k<=q;k++)
a[i][j][k]+=a[i][j-1][k];
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
for(int k=1;k<=q;k++)
a[i][j][k]+=a[i][j][k-1];
其实很好理解。
你考虑先解决一维,再将这个结果继承到下一维,如此类推。
时间复杂度:
。
利用这个东西,就可以算出高维前缀和。高维前缀和一般都是
的情况,一般来说就是求一个集合的子集这类的东西。