D. Valiant’s New Map
题意
题意:给我们一个n*m的矩阵,让我们求一个数k,满足k * k的子矩阵里面的每一个数都大于k,问我们k最大是多少。
思路
思路:这个题的话我们发现答案是具有单调性的,我们假设K就是我们要的答案的话,那么K+1一定是不成立的,我们子矩阵的范围扩大了,然后我们要满足的数还扩大了,所以肯定是不可能的,所以答案具有单调性,我们考虑二分。
二分我们可以通过一开始的矩阵a,我们建一个矩阵b,如果a[i][j]大于等于我们现在的k的话那么就是1,小于的话就是0。
建立好的话我们就可以通过二维前缀和求出子矩阵的值,如果有任何一个满足条件及等于我们矩阵中所有点的个数的话,就说明此时的k有可能是答案,我们就记录一下。最后直接输出最大值即可。
如果大家不了解二维前缀和的话可以看一下这篇文章传送门
AC代码
#include <bits/stdc++.h>
using namespace std;
int n, m;
vector<vector<int>> a;
bool check(int k)
{
vector<vector<int>> S(n + 1, vector<int>(m + 1, 0));
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] + (a[i][j] >= k);
for (int i = k; i <= n; i++)
for (int j = k; j <= m; j++)
{
int x = i - k + 1, y = j - k + 1;
if (S[i][j] - S[x - 1][j] - S[i][y - 1] + S[x - 1][y - 1] == k * k)
return true;
}
return false;
}
void solve()
{
cin >> n >> m;
a = vector<vector<int>>(n + 1, vector<int>(m + 1));
for (int i = 1; i <= n; i++)
for (int j = 1; j <= m; j++)
cin >> a[i][j];
int l = 1, r = min(n, m);
int ans = 0;
while (l < r)
{
int mid = l + r + 1 >> 1;
if (check(mid))
{
ans = max(ans, mid);
l = mid;
}
else
r = mid - 1;
}
/* for (int i = 1; i <= 50; i++)
{
int mid = (l + r) / 2;
if (check(mid))
{
ans = max(ans, mid);
l = mid + 1;
}
else
r = mid - 1;
} */
cout << max(ans, 1) << endl;
}
int main()
{
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
int T;
cin >> T;
while (T--)
{
solve();
}
return 0;
}