Woodyiiiiiii / LeetCode

My private record of Leetcode solution

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Leetcode 2536. Increment Submatrices by One / LCP 74 最强祝福力场

Woodyiiiiiii opened this issue · comments

2536. Increment Submatrices by One

2536. Increment Submatrices by One

这道题是周赛第二题,我没多想用暴力直接过了,但赛后看到使用其他语言是TLE的,所以正解肯定不是暴力。

这种题一下子就容易想到prefix sum,前缀和。在左上定点dp[r1][c1]和dp[r2+1][c2+1]加1,然后在dp[r2+1][c1]和dp[r1][c2+1]减1。那么重点是如何推算递进公式呢?

对于某个数dp[i][j],收到上和左的影响,自然加上两者,那么会出现重复的部分,所以要减去一半,减去左上角。

class Solution {
    public int[][] rangeAddQueries(int n, int[][] queries) {
        int[][] dp = new int[n][n];
        for (int[] query : queries) {
            int r1 = query[0], c1 = query[1], r2 = query[2], c2 = query[3];
            dp[r1][c1]++;
            if (r2 + 1 < n) dp[r2 + 1][c1]--;
            if (c2 + 1 < n) dp[r1][c2 + 1]--;
            if (r2 + 1 < n && c2 + 1 < n) dp[r2 + 1][c2 + 1]++;
        }
        int[][] ans = new int[n][n];
        for (int i = 0; i < n; ++i) {
            for (int j = 0; j < n; ++j) {
                ans[i][j] = dp[i][j];
                if (i > 0) {
                    ans[i][j] += ans[i - 1][j];
                }
                if (j > 0) {
                    ans[i][j] += ans[i][j - 1];
                }
                if (i > 0 && j > 0) {
                    ans[i][j] -= ans[i - 1][j - 1];
                }
            }
        }
        return ans;
    }
}

LCP 74 最强祝福力场

最强祝福力场
离散化+二维差分(Python/Java/C++/Go)

这道题首先要明白一点,就是最大叠加范围是一定会出现在上,而不一定是在顶点上,比如十字形交叉。

这个边就可能是所有横坐标和纵坐标打散后组合,会产生不同于顶点的点。所以这就是哈希去重组合:将横坐标和纵坐标用有序哈希表存储。

这也是离散化,将坐标和索引结合。又因为坐标会出现小数,可以用Double存储,或者对坐标乘2,因为线性交换不会改变相交关系。

然后,怎么表示矩阵范围呢?这就是涉及到二维差分的**:对一个矩阵左下下标+1,右上下标+1,左上下标-1,右下下标-1。

最后遍历所有点(也就是边)求最大值。

class Solution {
    public int fieldOfGreatestBlessing(int[][] forceField) {
        Set<Double> xSet = new TreeSet<>(), ySet = new TreeSet<>();
        for (int[] force : forceField) {
            Double r1 = force[0] - force[2] / 2.0, r2 = force[0] + force[2] / 2.0;
            xSet.add(r1);
            xSet.add(r2);
            Double c1 = force[1] - force[2] / 2.0, c2 = force[1] + force[2] / 2.0;
            ySet.add(c1);
            ySet.add(c2);
        }
        int m = xSet.size(), n = ySet.size();
        Double[] xArr = xSet.toArray(new Double[m]), yArr = ySet.toArray(new Double[n]);
        int[][] diff = new int[m][n];
        for (int[] force : forceField) {
            Double r1 = force[0] - force[2] / 2.0, r2 = force[0] + force[2] / 2.0;
            Double c1 = force[1] - force[2] / 2.0, c2 = force[1] + force[2] / 2.0;
            int x1 = Arrays.binarySearch(xArr, r1), x2 = Arrays.binarySearch(xArr, r2);
            int y1 = Arrays.binarySearch(yArr, c1), y2 = Arrays.binarySearch(yArr, c2);
            diff[x1][y1]++;
            if (y2 + 1 < n) diff[x1][y2 + 1]--;
            if (x2 + 1 < m) diff[x2 + 1][y1]--;
            if (x2 + 1 < m && y2 + 1 < n) diff[x2 + 1][y2 + 1]++;
        }
        int max = 0;
        for (int i = 0; i < m; i++) {
            for (int j = 0; j < n; j++) {
                diff[i][j] += (i > 0 ? diff[i - 1][j] : 0) + (j > 0 ? diff[i][j - 1] : 0) - (i > 0 && j > 0 ? diff[i - 1][j - 1] : 0);
                max = Math.max(max, diff[i][j]);
            }
        }
        return max;
    }
}