week37
363 - 矩形区域不超过 K 的最大数值和
这题说是hard,但是没能逃过枚举端点;
这里是通过枚举三个端点和一次二分查找来实现找到最接近k的差值,用到的就是二维前缀和
class Solution {
public:
vector<vector<int>> s;
public:
int get(int x1, int y1, int x2, int y2)
{
return s[x2][y2] - s[x1 - 1][y2] - s[x2][y1 - 1] + s[x1 - 1][y1 - 1];
}
int maxSumSubmatrix(vector<vector<int>>& matrix, int k) {
// 枚举三个边界 更新最大值
int n = matrix.size(), m = matrix[0].size();
s = vector<vector<int>>(n + 1, vector<int>(m + 1));
// 1. 构建二维前缀和
for(int i = 1; i <= n; i++)
for(int j = 1; j <= m; j++)
s[i][j] = s[i - 1][j] + s[i][j - 1] - s[i - 1][j - 1] + matrix[i - 1][j - 1];
// 2. 枚举三个端点 二分找最优解
int res = -1e9;
for(int x1 = 1; x1 <= n; x1++)
for(int x2 = x1; x2 <= n; x2++)
{
set<int> sset;
sset.insert(0);
// 遍历从0到y2 - 1
for(int y2 = 1; y2 <= m; y2++)
{
int si = get(x1, 1, x2, y2);
// si - sj <= k -> sj >= si - k
auto it = sset.lower_bound(si - k);
if(it != sset.end())
res = max(res, si - *it);
sset.insert(si);
}
}
return res;
}
};365 - 水壶问题
这个题还是狠经典的,有这么几个点:
两个水壶不可能同时半满不满, 必然有一个水壶是满的or空的
对一个不满不空的水壶,倒掉或加满都是没有意义的,等同于初始状态
所以,我们可以认为,对两个水壶的整体来看,每次操作要么就是倒空某个满的水壶,要么就是装满,要么就是互相倒;
对总水量的影响只有+-a 和 +-b 这四种
所以,最终求的就是ax+by = c 在 x + y <= c的前提下是否有解
裴蜀定理:ax+by=c有解当且仅当c可以被gcd(a, b)整除
再复习一下欧几里得算法和扩展欧几里得算法怎么写:
所以这个题就是判断一下是否c 可以被gcd(a, b) 整除即可,别忘了 x + y <= c这个额外的限制
367 - 有效的完全平方数
不让用sqrt 就是简单的二分查找 找平方根即可
这里不用担心溢出的问题
368 - 最大整除子集
整除是有传递性的,排序后只要保证相邻元素是可整除的即可
然后仿照最大上升子序列问题的dp解决方式来求
Last updated