其他分享
首页 > 其他分享> > P3397 地毯题解

P3397 地毯题解

作者:互联网

题目传送门

一、数组模拟

上来一看,无脑二维数组模拟啊,打一遍,提交!

#include <bits/stdc++.h>

using namespace std;
const int N = 1010;
int a[N][N];
int n, m;

int main() {
    scanf("%d%d", &n, &m);
    while (m--) {
        int x1, y1, x2, y2;
        cin >> x1 >> y1 >> x2 >> y2;
        for (int i = x1; i <= x2; i++)
            for (int j = y1; j <= y2; ++j)
                a[i][j]++;
    }
    for (int i = 1; i <= n; i++) {
        for (int j = 1; j <= n; j++)
            printf("%d ", a[i][j]);
        printf("\n");
    }
    return 0;
}

直接AC!书中说原题的数据范围较大,需要使用二维前缀和的思路,其实这么说是不严谨的,是二维差分的思路

本题数据范围为\(n<=1000,m<=1000\)。当\(n<=1000,m<=1000000\)甚至\(m<=10000000\)怎么办呢?
这时,我们亟需一个\(O(N)\)级别的算法来解决此问题:
这是一个非常典型的在二维数组中区域加减某个数字的问题,就是二维差分的模板。

一维前缀和与二维前缀和

一维差分与二维差分

二维差分解法:

#include <bits/stdc++.h>

using namespace std;
const int N = 1010;
int a[N][N];
int b[N][N];
int n, m;

/**
 * 功能:二维差分的模板
 * @param x1
 * @param y1
 * @param x2
 * @param y2
 * @param c
 */
void insert(int x1, int y1, int x2, int y2, int c) {
    b[x1][y1] += c;
    b[x2 + 1][y1] -= c;
    b[x1][y2 + 1] -= c;
    b[x2 + 1][y2 + 1] += c;
}

int main() {
    scanf("%d%d", &n, &m);
    while (m--) {
        int x1, y1, x2, y2;
        cin >> x1 >> y1 >> x2 >> y2;
        //对比二维差分的表示,四个加法运算,优化掉双重循环
        insert(x1, y1, x2, y2, 1);
    }

    //通过二维差分,还原成原始数组
    for (int i = 1; i <= n; i++) {
        for (int j = 1; j <= n; j++) {
            b[i][j] += b[i - 1][j] + b[i][j - 1] - b[i - 1][j - 1];
            printf("%d ", b[i][j]);
        }
        printf("\n");
    }
    return 0;
}

标签:y2,int,题解,x2,二维,P3397,y1,x1,地毯
来源: https://www.cnblogs.com/littlehb/p/15038719.html