前缀和初步
参考博客:https://www.cnblogs.com/OIerShawnZhou/p/7348088.html
谢谢大佬的博客= =
对于前缀和的创建
首先对0行0列置零
公式如下:
for(int i=1;i<=n;i++) for(int j=1;j<=m;j++) { cin>>a[i][j]; b[i][j]=b[i-1][j]+b[i][j-1]-b[i-1][j-1]+a[i][j]; }
二维前缀和
与一维前缀和类似,设s[i][j]表示所有a[i'][j']的和。(1≤i'≤i,1≤j'≤j)
有一点像“矩形的面积”那样,把一整块区域的值都加起来。
前缀和的用途
一般用来求区间和。
对于一维情况,现在我给出一个数列a,要求你回答m次询问,每次询问下标j到k的和。朴素的做法显然是对于每次询问都执行一次相加操作,然后输出结果。这样做是正确的,但是当m过大时就会导致计算次数过多而有可能超时。
超时的原因一目了然,重复计算。那么我们应该怎么改进这个方法呢?想象一下,我们如果先提前算好了每一个位置的前缀和,然后用s[k]-s[j],结果不就是我们这次询问的答案吗?这样便会使计算量大大减小。
对于二维的区间和,也是类似的。
![](https://images2017.cnblogs.com/blog/1212019/201708/1212019-20170811212508538-1358150065.png)
然后是区间查询:
int ans=b[x2][y2]-b[x2][y1-1]-b[x1-1][y2]+b[x1-1][y1-1];
然后全部代码:
//Good Luck~ #include<iostream> using namespace std; const int maxd=10000+10; int a[maxd][maxd],b[maxd][maxd]; int main() { ios::sync_with_stdio(0); cin.tie(0); cout.tie(0); int n,m; cin>>n>>m; for(int i=0;i<=m;i++) b[0][i]=0; for(int i=0;i<=n;i++) b[i][0]=0; for(int i=1;i<=n;i++) for(int j=1;j<=m;j++) { cin>>a[i][j]; b[i][j]=b[i-1][j]+b[i][j-1]-b[i-1][j-1]+a[i][j]; } for(int i=1;i<=n;i++) { for(int j=1;j<=m;j++) cout<<b[i][j]<<" "; cout<<endl; } int x1,x2,y1,y2; cin>>x1>>y1>>x2>>y2; int ans=b[x2][y2]-b[x2][y1-1]-b[x1-1][y2]+b[x1-1][y1-1]; cout<<ans; return 0; }