二维差分:
(转载自https://blog.csdn.net/qq_42815188/article/details/88752604)
1.将原数组s[][]的以(x1,y1)为左上角,以(x2,y2)为右下角的矩形区域里的每个数都加上c.
a[x1][y1] += c; a[x2 + 1][y1] -= c; a[x1][y2 + 1] -= c; a[x2 + 1][y2 + 1] += c;
2.差分数组a的前缀和即原数组.
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];
也可以省略数组a(用s代替a),直接
s[i][j] += s[i][j - 1] + s[i - 1][j] - s[i - 1][j - 1];
题解:
如果还不熟悉二维差分,这题可以用一维差分做出来,因为数据范围保证全开int不会爆.
每读入一个地毯,对其对应的y行进行一维差分即可.
(输出部分好像处理得不是很好)
#include <algorithm> #include <cstdio> #include <cstring> #include <iostream> using namespace std; int n, m, s[1010][1010]; int main(){ int x1, y1, x2, y2; cin >> n >> m; for(int i = 0; i < m; i++){ cin >> x1 >> y1 >> x2 >> y2; for(int j = y1; j <= y2; j++){ s[x1][j]++; s[x2 + 1][j]--; } } for(int i = 0; i < n; i++){ for(int j = 1; j <= n; j++){ s[i + 1][j] += s[i][j]; printf("%d ", s[i + 1][j]); } puts(""); } return 0; }
二维差分做法:
只需要稍微修改一下上面的AC代码:
#include <algorithm> #include <cstdio> #include <cstring> #include <iostream> using namespace std; int n, m, s[1010][1010]; int main(){ int x1, y1, x2, y2; cin >> n >> m; for(int i = 0; i < m; i++){ cin >> x1 >> y1 >> x2 >> y2; s[x1][y1]++; // 这四行不要打错了 s[x2 + 1][y2 + 1]++; s[x2 + 1][y1]--; s[x1][y2 + 1]--; } for(int i = 1; i <= n; i++){ for(int j = 1; j <= n; j++){ s[i][j] += s[i][j - 1] + s[i - 1][j] - s[i - 1][j - 1]; printf("%d ", s[i][j]); } puts(""); } return 0; }