前缀和
一维前缀和
一维前缀和主要是用于快速求出序列中某区间各元素之和
公式为: s[i] = s[i -1] + a[i]
s[i - 1] 表示前i-1个元素的总和 a[i]表示当前第i个元素的值 两个相加就得到了s[i] 表示前i个元素的总和
代码实现
#include <iostream>
using namespace std;
const int N = 1e5 + 10;
int a[N], s[N];
int n;
int main()
{
scanf("%d", &n);
for (int i = 1; i <= n; i ++ ) scanf("%d", &a[i]);
for (int i = 1; i <= n; i ++ )
{
s[i] = s[i - 1] + a[i];
}
// 一次循环写完
for (int i = 1; i <= n; i ++ )
{
int k;
scanf("%d", &k);
s[i] = s[i - 1] + k;
}
return 0;
}
二维前缀和
二维前缀和就是求大矩阵中某一小矩阵的元素总和
公式为: S[ i ][ j ] = S[ i - 1 ][ j ] + S[ i ][ j - 1 ] - S[ i - 1][ j - 1 ] + a[ i ][ j ]
加上q次询问的代码如下
#include <iostream>
using namespace std;
const int N = 1010;
int n, m, q;
int a[N][N], s[N][N];
int main()
{
scanf("%d%d%d", &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][j - 1] + s[i - 1][j] - s[i - 1][j - 1] + a[i][j];
while (q --)
{
int x1, y1, x2, 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;
}
差分
一维差分
一维差分的定义:表示原数列中两个相邻元素的差
差分就是前缀和的逆运算 本质上就是构造一个数组 让原数组是差分数组的前缀和数组
公式:d[i] = a[i] - a[i-1]
代码
#include <iostream>
using namespace std;
const int N = 100010;
int n, m;
int a[N], s[N];
int main()
{
cin >> n >> m;
for (int i = 1; i <= n; i++) scanf("%d", &a[i]);
for (int i = 1; i <= n; i++) s[i] = s[i - 1] + a[i];
while(m --)
{
int l, r;
scanf("%d%d", &l, &r);
printf("%d\n", s[r] - s[l - 1]);
}
return 0;
}
二维差分
二维差分的主要用处:快速地将一个区块中的所有元素都加上一个值 v
公式:d[i,j] = a[i,j] - a[i -1, j] - a[i, j - 1] + a[i - 1, j - 1] ( 1 <= i <= n)
假设A矩阵的左上角坐标为(x1,y1) 右下角坐标为(x2,y2)
对 A矩阵中该区块的每个元素都加上 v 的操作等价于进行下面四个操作:
d[x1, y1] += v;
d[x2 + 1, y1] -= v;
d[x1, y2 + 1] -= v;
d[x2 + 1, y2 + 1] += v;
代码
#include <iostream>
using namespace std;
const int N = 1010;
int n, m, q;
int a[N][N], s[N][N];
int main()
{
scanf("%d%d%d", &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][j - 1] + s[i - 1][j] - s[i - 1][j - 1] + a[i][j];
while (q --)
{
int x1, y1, x2, 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;
}