link
给定一个带权值的 n × m n×m n×m 网格,你可以选取一块边长为 l l l 的正方形区域当且仅当该区域的所有权值都大于等于 l l l,问可以选取的最大正方形区域的边长。
Game studio “DbZ Games” wants to introduce another map in their popular game “Valiant”. This time, the map named “Panvel” will be based on the city of Mumbai.
Mumbai can be represented as n × m n \times m n×m cellular grid. Each cell ( i , j ) (i, j) (i,j) ( 1 ≤ i ≤ n 1 \le i \le n 1≤i≤n ; 1 ≤ j ≤ m 1 \le j \le m 1≤j≤m ) of the grid is occupied by a cuboid building of height a i , j a_{i,j} ai,j .
This time, DbZ Games want to make a map that has perfect vertical gameplay. That’s why they want to choose an l × l l \times l l×l square inside Mumbai, such that each building inside the square has a height of at least l l l .
Can you help DbZ Games find such a square of the maximum possible size l l l ?
Each test contains multiple test cases. The first line contains the number of test cases t t t ( 1 ≤ t ≤ 1000 1 \leq t \leq 1000 1≤t≤1000 ). Description of the test cases follows.
The first line of each test case contains two positive integers n n n and m m m ( 1 ≤ n ≤ m 1 \le n \le m 1≤n≤m ; 1 ≤ n ⋅ m ≤ 1 0 6 1 \leq n \cdot m \leq 10^6 1≤n⋅m≤106 ).
The $ i $ -th of next n n n lines contains m m m integers a i , 1 , a i , 2 , … , a i , m a_{i,1}, a_{i,2}, \dots, a_{i,m} ai,1,ai,2,…,ai,m ( 1 ≤ a i , j ≤ 1 0 6 1 \leq a_{i,j} \leq 10^6 1≤ai,j≤106 ) — heights of buildings on the i i i -th row.
It’s guaranteed that the sum of n ⋅ m n \cdot m n⋅m over all test cases doesn’t exceed 1 0 6 10^6 106 .
For each test case, print the maximum side length l l l of the square DbZ Games can choose.
4
2 2
2 3
4 5
1 3
1 2 3
2 3
4 4 3
2 1 4
5 6
1 9 4 6 5 8
10 9 5 8 11 6
24 42 32 8 11 1
23 1 9 69 13 3
13 22 60 12 14 17
2
1
1
3
In the first test case, we can choose the square of side l = 2 l = 2 l=2 (i. e. the whole grid) since the heights of all buildings are greater than or equal to 2 2 2 .
In the second test case, we can only choose the side as 1 1 1 , so the answer is 1 1 1 .
In the third test case, there are no squares of size 2 2 2 that have all buildings of height at least 2 2 2 , so the answer is 1 1 1 .
思路:用二维前缀和数组来存储是否符合条件。
考虑在一个矩阵中,如何计算从 ( 1 , 1 ) ( 1 , 1 ) (1,1) 到 ( x , y ) ( x , y ) (x,y) 这一部分的和呢?可以用 f i , j f_{i,j} fi,j 表示从 ( 1 , 1 ) ( 1 , 1 ) (1,1) 到 ( i , j ) ( i ,j ) (i,j) 的总和,则 f i , j ← f i − 1 , j + f i , j − 1 − f i − 1 , j − 1 + a i , j f_{i,j} \gets f_{i-1,j} + f_{i,j-1} - f_{i-1,j-1} + a_{i,j} fi,j←fi−1,j+fi,j−1−fi−1,j−1+ai,j,中间之所以要减去是因为重复计算了。
因为并不确定 n n n 和 m m m 的值,所以要用 vector
,注意要先动态开空间之后才能当作数组使用。
#include
using namespace std;
#define ll long long
const ll N=1e6+10;
ll T,n,m,ans,t,l,r,mid;
vector<ll> a[N],f[N];
bool check(ll p){
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
f[i][j]=a[i][j]<mid;
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
f[i][j]+=f[i-1][j]+f[i][j-1]-f[i-1][j-1];
for(int i=1;i+p<=n;i++)
for(int j=1;j+p<=m;j++)
if(!(f[i+p][j+p]+f[i-1][j-1]-f[i-1][j+p]-f[i+p][j-1]))
return 1;
return 0;
}
int main(){
ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
cin>>T;
while(T--){
cin>>n>>m;
f[0].clear();
for(int i=0;i<=m;i++) f[0].push_back(0);
for(int i=1;i<=n;i++){
a[i].clear();
a[i].push_back(0);
f[i].clear();
f[i].push_back(0);
for(int j=1;j<=m;j++){
cin>>t;
a[i].push_back(t);
f[i].push_back(0);
}
}
l=1,r=n;
while(l<=r){
mid=l+r>>1;
if(check(mid-1)) l=mid+1,ans=mid;
else r=mid-1;
}
cout<<ans<<"\n";
}
return 0;
}