Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

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

Open
Woodyiiiiiii opened this issue Jan 16, 2023 · 0 comments

Comments

@Woodyiiiiiii
Copy link
Owner

Woodyiiiiiii commented Jan 16, 2023

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;
    }
}
@Woodyiiiiiii Woodyiiiiiii changed the title Leetcode 2536. Increment Submatrices by One Leetcode 2536. Increment Submatrices by One / LCP 74 最强祝福力场 Apr 25, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant