Planting Trees
The semester is finally over and the summer holiday is coming. However, as part of your university's graduation requirement, you have to take part in some social service during the holiday. Eventually, you decided to join a volunteer group which will plant trees in a mountain.
To simplify the problem, let's represent the mountain where trees are to be planted with an N×NN×N grid. Let's number the rows 1 1 to N N from top to bottom, and number the columns 1 1 to N N from left to right. The elevation of the cell in the i i-th row and j j-th column is denoted by ai,jai,j. Your leader decides that trees should be planted in a rectangular area within the mountain and that the maximum difference in elevation among the cells in that rectangle should not exceed M. In other words, if the coordinates of the top-left and the bottom-right corners of the rectangle are (x1,y1)(x1,y1) and (x2,y2)(x2,y2), then the condition |ai,j−ak,l|≤M|ai,j−ak,l|≤M must hold for x1≤i,k≤x2, y1≤j,l≤y2x1≤i,k≤x2, y1≤j,l≤y2. Please help your leader calculate the maximum possible number of cells in such a rectangle so that he'll know how many trees will be planted.
输入描述:
The input contains multiple cases. The first line of the input contains a single integer T (1≤T≤1000)T (1≤T≤1000), the number of cases.
For each case, the first line of the input contains two integers N (1≤N≤500)N (1≤N≤500) and M (0≤M≤105)M (0≤M≤105). The following N lines each contain N integers, where the j j-th integer in the i i-th line denotes ai,j (1≤ai,j≤105)ai,j (1≤ai,j≤105).
It is guaranteed that the sum of N3N3 over all cases does not exceed 25⋅10725⋅107.
输出描述:
For each case, print a single integer, the maximum number of cells in a valid rectangle.
示例1
输入
2
2 0
1 2
2 1
3 1
1 3 2
2 3 1
3 2 1
输出
1
4
题意:求一个子矩阵的大小,使得子矩阵的最大值 - 最小值 <= m,求这个最大的子矩阵大小。
思路:枚举两行,在枚举的同时可以求得这些列的最小值与最大值。也就是说这些最小值与最大值就可以代表当前枚举的行之间的矩阵。其实也就是降维,问题就转化成了 求区间最大长度,使得区间的最大 - 最小 <= m。然后利用单调队列进行求解即可。用deque写单调队列应该是会T的,这里用的数组模拟写的单调队列
Code:
#include<bits/stdc++.h>
using namespace std;
#define ls rt<<1
#define rs (rt<<1)+1
#define ll long long
#define fuck(x) cout<<#x<<" "<<x<<endl;
const int inf=0x3f3f3f3f;
typedef pair<int,int> pii;
const int maxn=1e6+10;
int d[4][2]= {1,0,-1,0,0,1,0,-1};
int mp[505][505],minn[505],maxx[505];
int q[2][505],h[2],t[2];
int main() {
int _,n,m,ans,now;
scanf("%d",&_);
while(_--) {
ans=0;
scanf("%d%d",&n,&m);
for(int i=1; i<=n; i++)
for(int j=1; j<=n; j++)
scanf("%d",&(mp[i][j]));
for(int i=1; i<=n; i++) {
for(int j=i; j<=n; j++) {
for(int k=1; k<=n; k++)
if(j==i)
minn[k]=maxx[k]=mp[i][k];
else
minn[k]=min(minn[k],mp[j][k]),maxx[k]=max(maxx[k],mp[j][k]);
h[0]=1;t[0]=0;
h[1]=1;t[1]=0;
now = 1;
for(int k=1; k<=n; k++) {
if(!(t[0]-h[0]+1)||maxx[q[0][t[0]]]>maxx[k])
q[0][++t[0]]=k;
else {
while((t[0]-h[0]+1)&&maxx[q[0][t[0]]]<=maxx[k])
--t[0];
q[0][++t[0]]=k;
}
if(!(t[1]-h[1]+1)||minn[q[1][t[1]]]<minn[k])
q[1][++t[1]]=k;
else {
while((t[1]-h[1]+1)&&minn[q[1][t[1]]]>=minn[k])
--t[1];
q[1][++t[1]]=k;
}
while((t[0]-h[0]+1)&&(t[1]-h[1]+1)&&abs(maxx[q[0][h[0]]]-minn[q[1][h[1]]])>m) {
if(q[0][h[0]]<q[1][h[1]])
now=q[0][h[0]]+1,++h[0];
else
now=q[1][h[1]]+1,++h[1];
}
if((t[0]-h[0]+1)&&(t[1]-h[1]+1)){
// printf("%d %d %d %d\n",i,j,k - now + 1,now);
ans=max(ans,(j-i+1)*(k-now+1));
}
}
}
}
printf("%d\n",ans);
}
return 0;
}