璟雯院

珺璟如晔,雯华若锦

用户工具

站点工具


icpc:problems:valiant_s_new_map
problems
名称valiant_s_new_map
题目编号841D
来源CodeForces
算法分类前缀和, 二分
难易程度看懂题解

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 由 温婕莺