我有矩阵mat[m][n]和q查询。

In each query I have one of these 2 types of operations
1. Update MAT[x][y] with k where x,y and k will be given
2. return sum of sub rectangle where left top corner indices are (x1,y1) and right bottom indices are (x2,y2).

前-
Mat -
1 1 1 1
1 1 1 1
1 1 1 1
queries
type 1,2,2,5
type 2,1,1,3,3 => 13(output)

最佳答案

这个问题的标准解决方案是二维binary index tree。它可以在每个查询的O(log n * log m)时间内执行两个所需的操作,并占用O(n * m)额外空间(其中nm是给定矩阵的维数)它效率高,而且相对容易实现。这是我的代码:

/**
 * Instances of this class represent a two-dimensional binary index tree.
 *
 * They support the following operations:
 * 1. Updating the value of one element.
 * 2. Finding the sum of all elements in a specified rectangle.
 *
 * The time complexity of both operation is O(log n * log m), where n and m
 * are the initial matrix dimensions.
 */
template<class T>
class Bit2D {
public:
    /**
     * Creates a new instance of this class using the matrix as the initial
     * matrix.
     * The matrix must be non-empty.
     */
    Bit2D(const std::vector<std::vector<T>>& matrix): _matrix(matrix) {
        _rowsCount = matrix.size();
        _colsCount = matrix[0].size();
        _sum.assign(_rowsCount, std::vector<T>(_colsCount, 0));
        for (int row = 0; row < _rowsCount; row++) {
            for (int col = 0; col < _colsCount; col++) {
                _update(row, col, _matrix[row][col]);
            }
        }
    }

    /**
     * Returns the sum of all elements in the
     * ((lowerRow, lowerCol), (upperRow, upperCol)) rectangle.
     * All bounds are inclusive.
     * lowerRow must be not greater than upperRow.
     * lowerCol must be not greater than upperCol.
     *
     * If any of these four values is outside the bounds of the initial matrix,
     * undefined behavior is invoked.
     */
    T getSum(int lowerRow, int lowerCol, int upperRow, int upperCol) const {
        return _getSum(upperRow, upperCol) - _getSum(upperRow, lowerCol - 1)
            - _getSum(lowerRow - 1, upperCol)
            + _getSum(lowerRow - 1, lowerCol - 1);
    }

    /**
     * Sets the value of the (row, col) element to newValue.
     *
     * If row or col is outside the bounds of the initial matrix, undefined
     * behavior is invoked.
     */
    void update(int row, int col, T newValue) {
        _update(row, col, newValue - _matrix[row][col]);
        _matrix[row][col] = newValue;
    }

private:
    std::vector<std::vector<T>> _matrix;
    std::vector<std::vector<T>> _sum;
    int _rowsCount;
    int _colsCount;

    int _getPrevious(int index) const {
        return (index & (index + 1)) - 1;
    }

    int _getNext(int index) const {
        return index | (index + 1);
    }

    T _getSum(int upperRow, int upperCol) const {
        T res = 0;
        for (int row = upperRow; row >= 0; row = _getPrevious(row)) {
            for (int col = upperCol; col >= 0; col = _getPrevious(col)) {
                res += _sum[row][col];
            }
        }
        return res;
    }

    void _update(int row, int col, T delta) {
        for (int curRow = row; curRow < _rowsCount; curRow = _getNext(curRow)) {
            for (int curCol = col; curCol < _colsCount; curCol = _getNext(curCol)) {
                _sum[curRow][curCol] += delta;
            }
        }
    }
};

关于algorithm - 用于计算子矩形总和的算法,该子矩形也允许更新,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/28541234/

10-10 20:08