Loading

二维前缀和 & 二维差分

二维前缀和

求二维前缀和后,能够实现 \(O(1)\) 求原数组二维区间和,但是不支持修改。

ll n, m, sum2[N][N], c[N][N];

void Sum2_pre()
{
    fr(i, 1, n)
        fr(j, 1, m)
            sum2[i][j] = sum2[i-1][j] + sum2[i][j-1] - sum2[i-1][j-1] + c[i][j];
}

ll Sum2(ll x1, ll y1, ll x2, ll y2)
{
    return sum2[x2][y2] + sum2[x1-1][y1-1] - sum2[x1-1][y2] - sum2[x2][y1-1];
}

二维差分

先预处理出差分数组,之后可以实现 \(O(1)\) 原数组二维区间修改。

将差分数组还原为原数组的复杂度是 \(O(n^2)\) 的。

ll n, m, cha2[N][N], c[N][N];

void Cha2_pre() // 预处理差分数组
{
    fr(i, 1, n)
        fr(j, 1, m)
            cha2[i][j] = c[i][j] - c[i][j-1] - c[i-1][j] + c[i-1][j-1];
}

void Cha2(ll x1, ll y1, ll x2, ll y2, ll K) // 原数组二维区间修改
{
    cha2[x1][y1] += K;
    cha2[x2 + 1][y1] -= K;
    cha2[x1][y2 + 1] -= K;
    cha2[x2 + 1][y2 + 1] += K;
}

void Cha2_nxt() // 还原差分数组
{
    fr(i, 1, n)
        fr(j, 1, m)
        {
            cha2[i][j] = cha2[i-1][j] + cha2[i][j-1] - cha2[i-1][j-1] + cha2[i][j];
            c[i][j] = cha2[i][j];
        }
}


int main()
{
    n = re; m = re;
    Cha2_pre();
    fr(i, 1, 5)
    {
        ll a = re, b = re, c = re, d = re, e = re;
        Cha2(a, b, c, d, e);
    }
    Cha2_nxt();

    fr(i, 1, n)
    {
        fr(j, 1, m) W(c[i][j], ' ');
        puts("");
    }
    return 0;
}

输入

10 10
1 1 10 10 1
2 2 9 9 1
3 3 8 8 -1
4 4 7 7 2
5 5 6 6 1

输出

1 1 1 1 1 1 1 1 1 1 
1 2 2 2 2 2 2 2 2 1
1 2 1 1 1 1 1 1 2 1
1 2 1 3 3 3 3 1 2 1
1 2 1 3 4 4 3 1 2 1
1 2 1 3 4 4 3 1 2 1
1 2 1 3 3 3 3 1 2 1
1 2 1 1 1 1 1 1 2 1
1 2 2 2 2 2 2 2 2 1
1 1 1 1 1 1 1 1 1 1
posted @ 2024-10-10 20:07  EdisonBa  阅读(9)  评论(0编辑  收藏  举报