icpc:problems:valiant_s_new_map
valiant_s_new_map
想法
首先要想到这个答案最大就是$10^6$,然后n*m也是$10^6$,所以就算枚举一次整个矩阵也就这么大。
其次再想到二分,因为可以用二维前缀和(类似于位图)的操作来判断x*x大小的矩阵的可行性,所以这个答案可以二分。
之后这个二分要得到尽可能大的答案,要保证l是最后的答案,所以划分区间是[l, mid-1]与[mid, r],所以每次取右端点 (l + r + 1) / 2。
代码实现
#include<iostream> #include<cmath> #include<vector> using namespace std; int n, m; bool check(int x, vector<vector<int> >maps) { vector<vector<int> >sum(n+10, vector<int>(m+10)); int temp; for (int i = 0; i < n; ++i) { for (int j = 0; j < m; ++j) { if(maps[i][j] < x) temp = 0; else temp = 1; sum[i+1][j+1] = sum[i+1][j] + sum[i][j+1] - sum[i][j] + temp; } } for (int i = x; i <= n; ++i) { for (int j = x; j <= m; ++j) { temp = sum[i][j] - sum[i-x][j] - sum[i][j-x] + sum[i-x][j-x]; if(temp == x * x) return true; } } return false; } int main() { ios_base::sync_with_stdio(false); cin.tie(NULL); cout.tie(NULL); int T; cin >> T; while(T--) { cin >> n >> m; vector<vector<int> >maps(n, vector<int>(m)); for (int i = 0; i < n; ++i) for (int j = 0; j < m; ++j) cin >> maps[i][j]; int l = 0, r = min(n, m), mid; while(l < r) { mid = (l + r + 1) / 2; if(check(mid, maps)) l = mid; else r = mid-1; } cout << l << endl; } return 0; }
/app/www/public/data/pages/icpc/problems/valiant_s_new_map.txt · 最后更改: 2023/09/30 14:00 由 温婕莺