前缀和和差分
前缀和的操作可以类比数学中数列的前n项和,当我们在频繁询问某个区间内元素之和的时候,使用前缀和数组首先预处理,再进行查找,可以将每一次的询问复杂度下降到 O ( 1 ) O(1) O(1)
算法模版
一维前缀和(acwing.795)
#include <bits/stdc++.h>
using namespace std;
const int N = 100010;
int a[N];
int n, m;
int main()
{
cin >> n >> m;
for(int i = 1; i <= n; i ++) scanf("%d", &a[i]);
//求前缀和
for(int i = 1; i <= n; i++) a[i] += a[i - 1];
while(m --)
{
int l, r;
cin >> l >> r;
cout << a[r] - a[l - 1] << endl;
}
return 0;
}
二维前缀和(acwing.796)
#include <bits/stdc++.h>
using namespace std;
const int N = 1010;
int a[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 ++)
a[i][j] += (- a[i - 1][j - 1] + a[i - 1][j] + a[i][j - 1]);
while(q --)
{
int x1, y1, x2, y2;
scanf("%d%d%d%d", &x1, &y1, &x2, &y2);
int res = a[x2][y2] - a[x2][y1 - 1] - a[x1 - 1][y2] + a[x1 - 1][y1 - 1];
cout << res << endl;
}
return 0;
}
一维差分(acwing.797)
注意差分操作一定要使用另一个数组来储存,同一个数组会出错
#include <iostream>
using namespace std;
const int N = 100010;
int a[N], b[N];
int main()
{
int n, m;
cin >> n >> m;
for(int i = 1; i <= n; i++) scanf("%d", &a[i]);
//处理差分
for(int i = 1; i <= n; i++) b[i] = a[i] - a[i - 1];
while(m --)
{
int l, r, c;
scanf("%d%d%d", &l, &r, &c);
b[l] += c;
b[r + 1] -= c;
}
for(int i = 1; i <= n; i++) b[i] += b[i - 1];
for(int i = 1; i <= n; i++) printf("%d ", b[i]);
return 0;
}
二维差分(acwing.798)
#include <iostream>
using namespace std;
const int N = 1010;
int a[N][N], b[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 ++)
b[i][j] = a[i][j] - a[i][j - 1] - a[i - 1][j] + a[i - 1][j - 1];
while(q --)
{
int x1, y1, x2, y2, c;
scanf("%d%d%d%d%d", &x1, &y1, &x2, &y2, &c);
b[x1][y1] += c, b[x1][y2 + 1] -= c, b[x2 + 1][y1] -= c, b[x2 + 1][y2 + 1] += c;
}
for(int i = 1; i <= n; i++)
for(int j = 1; j <= m; j++)
b[i][j] += b[i][j - 1] + b[i - 1][j] - b[i - 1][j - 1];
for(int i = 1; i <= n; i++)
{
for(int j = 1; j <= m; j ++)
printf("%d ",b[i][j]);
puts("");
}
return 0;
}