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 - 水壶问题

这个题还是狠经典的,有这么几个点:

  1. 两个水壶不可能同时半满不满, 必然有一个水壶是满的or空的

  2. 对一个不满不空的水壶,倒掉或加满都是没有意义的,等同于初始状态

  3. 所以,我们可以认为,对两个水壶的整体来看,每次操作要么就是倒空某个满的水壶,要么就是装满,要么就是互相倒;

  4. 对总水量的影响只有+-a 和 +-b 这四种

所以,最终求的就是ax+by = cx + y <= c的前提下是否有解

裴蜀定理ax+by=c有解当且仅当c可以被gcd(a, b)整除

再复习一下欧几里得算法和扩展欧几里得算法怎么写:

所以这个题就是判断一下是否c 可以被gcd(a, b) 整除即可,别忘了 x + y <= c这个额外的限制

367 - 有效的完全平方数

不让用sqrt 就是简单的二分查找 找平方根即可

这里不用担心溢出的问题

368 - 最大整除子集

整除是有传递性的,排序后只要保证相邻元素是可整除的即可

然后仿照最大上升子序列问题的dp解决方式来求

Last updated