前缀和初步

参考博客: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],结果不就是我们这次询问的答案吗?这样便会使计算量大大减小。
对于二维的区间和,也是类似的。
 
 

 

然后是区间查询:

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;
}

 

 

 
posted @ 2019-02-26 19:15  zzRh_5479  阅读(127)  评论(0编辑  收藏  举报