NeFut Logo NeFut
Admin Login

Efficient Interval Updates and Recovery: A Deep Dive into Difference Arrays

Published at: 2026-05-27 09:17 Last updated: 2026-06-06 13:04
#algorithm #Dynamic Programming #Data Structure

Core Logic and Mathematical Principles

The difference array is the inverse operation of the prefix sum. Its physical essence is to convert global interval modifications into local endpoint corrections, achieving a dimensionality reduction for interval operations.

Let the original sequence be $A$, and the difference sequence be $D$. The two satisfy the following algebraic relationship:

$$D[i] = \begin{cases} A[i] & i = 1 \\ A[i] - A[i-1] & i > 1 \end{cases}$$

From the definition, the original sequence $A$ is actually the prefix sum sequence of the difference sequence $D$:

$$A[i] = \sum_{k=1}^{i} D[k]$$

When we need to add an increment $v$ to the entire interval $[l, r]$ of the original sequence, if we directly modify it in a brute-force manner, the time complexity would be $O(N)$. Observing the internal properties of the difference structure: for any position $l < i \le r$, since both $A[i]$ and $A[i-1]$ have been incremented by $v$, their relative difference $A[i] - A[i-1]$ remains unchanged, meaning $D[i]$ does not need any modification. The only two boundaries that truly experience a change are:

  1. $A[l]$ has increased by $v$ compared to $A[l-1]$, so $D[l]$ is increased by $v$.
  2. $A[r+1]$ has increased less than $v$ compared to $A[r]$, so $D[r+1]$ is decreased by $v$.

By reducing the interval problem to two-point modifications, the complexity of a single operation is suppressed to $O(1)$.


Algorithm Derivation

1. One-Dimensional Difference Maintenance and Restoration

For $M$ independent interval modifications $(l, r, v)$, we directly perform the operations on the difference array $D$:

$$D[l] \leftarrow D[l] + v$$

$$D[r+1] \leftarrow D[r+1] - v$$

After the modifications, we can utilize the prefix sum recursive relationship $A[i] = A[i-1] + D[i]$ to offline restore the entire original sequence $A$ in $O(N)$ time.

2. Two-Dimensional Matrix Difference Derivation

In a two-dimensional matrix, if we want to add $v$ to the entire submatrix defined by the top-left corner $(x_1, y_1)$ and the bottom-right corner $(x_2, y_2)$, using the two-dimensional inclusion-exclusion principle, our two-point modifications in the two-dimensional difference matrix $D$ evolve into four-point modifications. Based on the reverse topological structure of the two-dimensional prefix sum, the modification equations are:

$$D[x_1][y_1] \leftarrow D[x_1][y_1] + v$$

$$D[x_2+1][y_1] \leftarrow D[x_2+1][y_1] - v$$

$$D[x_1][y_2+1] \leftarrow D[x_1][y_2+1] - v$$

$$D[x_2+1][y_2+1] \leftarrow D[x_2+1][y_2+1] + v$$

When restoring the original matrix, we perform an $O(N \times M)$ state scan using the two-dimensional prefix sum state transition equations.


C++ Standard Source Code

#include <iostream>
#include <vector>

using namespace std;

// Demonstration of the modification and restoration process of a two-dimensional difference matrix
void solveMatrixDifference() {
    int n, m, p;
    if (!(cin >> n >> m >> p)) return;

    // 1-indexed boundary to prevent out-of-bounds crashes at x2+1 or y2+1, allocate 2 extra rows and columns as a safety buffer
    vector<vector<long long>> d(n + 2, vector<long long>(m + 2, 0));

    // P interval increment modifications
    for (int i = 0; i < p; ++i) {
        int x1, y1, x2, y2;
        long long v;
        cin >> x1 >> y1 >> x2 >> y2 >> v;

        // Key point: 4-point modification based on the inclusion-exclusion principle, a single sign error leads to zero
        d[x1][y1] += v;
        d[x2 + 1][y1] -= v;
        d[x1][y2 + 1] -= v;
        d[x2 + 1][y2 + 1] += v;
    }

    // O(N*M) prefix sum restoration of the matrix
    for (int i = 1; i <= n; ++i) {
        for (int j = 1; j <= m; ++j) {
            // Critical pitfall: during restoration, we must use the difference array itself for two-dimensional prefix sum recursive updates
            d[i][j] = d[i - 1][j] + d[i][j - 1] - d[i - 1][j - 1] + d[i][j];
            cout << d[i][j] << (j == m ? "" : " ");
        }
        cout << "\n";
    }
}

int main() {
    // Break the standard stream synchronization constant
    ios_base::sync_with_stdio(false);
    cin.tie(NULL);

    solveMatrixDifference();

    return 0;
}

NOIP Practical Pitfall Guide

  1. Memory Out-of-Bounds Access Caused by Right Endpoint Increment ($r+1$)
    The difference modification must involve $D[r+1]$ or the two-dimensional $D[x_2+1][y_2+1]$. When the input modification boundary exactly equals the upper limit of the data range $N$, $r+1$ will directly point to $N+1$. If the array is only allocated to size $N$, it will trigger a segmentation fault or hidden memory adjacency out-of-bounds write, causing other variable values to be bizarrely overwritten. It is essential to develop the habit of allocating the difference array space to at least $N + 2$.
  2. Accumulation Overflow During Prefix Sum Restoration
    Even if the single modification increment $v$ is relatively small, if the number of modification operations $M$ reaches the level of $10^5$, the final original element values after frequent interval additions can easily exceed the int limit of $2 \times 10^9$. If one tries to be economical and defines the difference array as int, integer overflow will occur during the prefix sum accumulation phase, resulting in negative values in the restored data. All difference arrays and restoration variables must be stored using long long.

Classic NOIP/Luogu Problems

1. Luogu P3397 Carpet

2. Luogu P1083 [NOIP2012 Advanced Group] Borrowing Classrooms

Original Source: local://2.2

[h] Back to Home