二維字首和 & 二維差分

EdisonBa發表於2024-10-10

二維字首和

求二維字首和後,能夠實現 \(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

相關文章