一维,二维差分 (P3397 地毯)

二维差分:

(转载自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 Code

二维差分做法:

只需要稍微修改一下上面的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;
}    
二维差分AC Code
原文地址:https://www.cnblogs.com/Gaomez/p/14162578.html