Leetcode 2536. Increment Submatrices by One / LCP 74 最强祝福力场
Woodyiiiiiii opened this issue · comments
woodyiiiiiii commented
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;
}
}