ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

一维二维前缀和详解

2022-09-12 01:00:25  阅读:77  来源: 互联网

标签:前缀 int 复杂度 二维 详解 一维 例题


目录

一、一维前缀和

1.前缀和是啥

前缀和其实就是用一个数组S存下数组a的前缀的和,这样话方便以后的查找,提高查找的速度。

2.一维前缀的时间复杂度

因为是遍历一遍数组a就可以得到我们的前缀和数组,所以前缀和的时间复杂度是O(n)。
如果是m次查找的话,我们就可以做到O(n+m)的时间复杂度。

3.一维前缀和公式的推导

一维的前缀和比较简单,这样的话我们先推导一下一维的前缀和的公式。

为了方便的话,我们一般在用前缀和的时候数组从下标为1的地方开始读入。这样是为了防止数组越界,我们可以这样考虑,当前我们已经该算下标为i的前缀和,因此我们这时肯定已经算过了下标为i-1的前缀和,这是我们这时只需要用下标为i-1的前缀和加上当前的下标为i的那个值,是不是就可以得到下标为i的前缀和。

于是我们可以很容易的得到一维前缀和的公式$$S[i]=S[i-1]+a[i]$$

for(int i = 1; i <= n; i ++)
  s[i] = S[i - 1] + a[i[]];

通过这样的一段代码就可以求出a数组的前缀和数组S,那我们知道了这个概念的话怎么用呢,我们接下来就看一道例题

4.一维前缀和的例题

AcWing前缀和例题
思路:就是一个非常裸的前缀和,然后进行m次查询即可,如果我们每次都进行遍历求和的话就会超时。
参考代码

#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;

const int N = 1e5 + 10;
int a[N],S[N];

int main()
{
     ios::sync_with_stdio(false);
     cin.tie(0);
     cout.tie(0);
     int n,m;
     cin>>n>>m;
     for(int i=1;i<=n;i++)    cin>>a[i];
     for(int i=1;i<=n;i++)    S[i]=S[i-1]+a[i];
     while(m--)
     {
          int l,r;
          cin>>l>>r;
          cout<<S[r]-S[l-1]<<endl;
     }
     return 0;
}

二、二维前缀和

1.二维前缀和的时间复杂度

二维前缀和的时间复杂度其实可以类比一维的时间复杂度,就是把这个二维数组遍历一遍,这样的话就是O(n*m)的时间复杂度

2.二维前缀和公式的推导

二维的前缀和就比一维的麻烦一些,我们没办法直接求出我们需要的所以我们只能先算出一个然后再减去重复的部分,最后我们可以得到$$s[i][j]=s[i-1][j]+s[i][j-1]-s[i-1][j-1]+a[i][j]$$

    for (int i = 1; i <= n; i++)
          for (int j = 1; j <= m; j++)
               S[i][j] = S[i - 1][j] + S[i][j - 1] - S[i - 1][j - 1] + a[i][j];

3.二维前缀和的子矩阵的查询

子矩阵也不是直接就可以查出来我们也只能用公式进行计算和上面求前缀和的过程差不多$$s[x2][y2]-s[x1-1][y2]-s[x2][y1-1]+s[x1-1][y1-1]$$

4.二维前缀和的例题

AcWing二维前缀和的例题
思路:就是简单的二维前缀和,正常的直接加的话会超时

#include <bits/stdc++.h>
using namespace std;

const int N = 1e3 + 10;
int a[N][N], s[N][N];

int main()
{
     int n, m, q;
     cin >> n >> m >> q;
     for (int i = 1; i <= n; i++)
     {
          for (int j = 1; j <= m; j++)
          {
               scanf("%d", &a[i][j]);
          }
     }
     for (int i = 1; i <= n; i++)
     {
          for (int j = 1; j <= m; j++)
          {
               s[i][j] = s[i - 1][j] + s[i][j - 1] - s[i - 1][j - 1] + a[i][j];
          }
     }
     while (q--)
     {
          int x1, x2, y1, y2;
          scanf("%d%d%d%d", &x1, &y1, &x2, &y2);
          printf("%d\n", s[x2][y2] - s[x1 - 1][y2] - s[x2][y1 - 1] + s[x1 - 1][y1 - 1]);
     }
     return 0;
}

标签:前缀,int,复杂度,二维,详解,一维,例题
来源: https://www.cnblogs.com/byAttention/p/16685257.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有