其实并不是很难的东西,只是怕又忘记了所以才写博客。

前缀和

构造数组b为输入数组a的前缀和,输出一段数列的和时时间复杂度为O(1),适合大量的输出。

一维前缀和

模板题

显然无什么好说的

在输入时b[i] = b[i - 1] + a[i]以构造前缀和数组即可

代码如下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
#include <bits/stdc++.h>

using namespace std;
const int lxb = 1e5 + 10;
int q[lxb];
int n, m;
int main()
{
cin >> n >> m;
for(int i = 1; i <= n; i ++)
{
int x;
cin >> x;
q[i] = q[i - 1] + x;
}
for(int i = 1; i <= m; i ++)
{
int l, r;
cin >> l >> r;
cout << q[r] - q[l - 1] << endl;
}

return 0;
}

二维前缀和

模板题

其实本质上差别不大

简单推理便可以得到x1,y1,x2,y2区间查询的和为

s[x2][y2] - s[x1 - 1][y2] - s[x2][y1 - 1] + s[x1 - 1][y1 - 1]

代码如下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
#include <bits/stdc++.h>

using namespace std;

const int lxb = 1010;
int a[lxb][lxb],s[lxb][lxb];
int n, m, q;

int main()
{
cin >> n >> m >> q;
for(int i = 1; i <= n; i ++)
{
for(int j = 1; j <= m; j ++)
{
scanf("%d",&a[i][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);
int ans = s[x2][y2] - s[x1 -1][y2] - s[x2][y1 -1] + s[x1 -1][y1 -1];
cout << ans << endl;
}
return 0;
}

差分

差分便是构造的b数组的前缀和为输入数组a的前缀和,改变一个区间数据的时间复杂度为O(1),适合频繁插入数据。

自己一般会理解为反向前缀和

一维差分

模板题

无话可说

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
#include <iostream>

using namespace std;

const int N = 100010;

int n, m;
int a[N], b[N];

void insert(int l, int r, int c)
{
b[l] += c;
b[r + 1] -= c;
}

int main()
{
scanf("%d%d", &n, &m);
for (int i = 1; i <= n; i ++ ) scanf("%d", &a[i]);

for (int i = 1; i <= n; i ++ ) insert(i, i, a[i]);

while (m -- )
{
int l, r, c;
scanf("%d%d%d", &l, &r, &c);
insert(l, r, 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;
}

二维差分

其实也是一样的道理,简单推理便可以得到

若想使x1,y1,x2,y2区间的数都加上加上一个c

只需要对b数组做以下操作

b[x1][y1] += c

b[x1][y2 + 1] -= c

b[x2 + 1][y1], -= c

b[x2 + 1][y2 + 1] += c

模板题

代码如下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60

#include <bits/stdc++.h>

using namespace std;

const int lxb = 1e3 + 10;

int n, m, q;

int a[lxb][lxb], b[lxb][lxb];

void insert (int x1, int y1, int x2, int y2, int c)
{
b[x1][y1] += c;
b[x1][y2 + 1] -= c;
b[x2 + 1][y1] -= c;
b[x2 +1][y2 + 1] += c;
}

int main()
{
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 ++)
{
insert(i,j,i,j,a[i][j]);
}

while(q --)
{
int x1,y1,x2,y2,c;
cin >> x1 >> y1 >> x2 >> y2 >> c;
insert(x1,y1,x2,y2,c);
}
for(int i = 1; i <= n; i ++)
{
for(int j = 1; j <= m; j ++)
{
b[i][j] += b[i - 1][j] + b[i][j - 1] - 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;
}