You are given a grid g consisting of n rows each of which is divided into m columns. The grid contains unique values between 1 and n×m
(inclusive).
Also, you are given two values h
and w, and your task is to find the smallest median value that can be found in a rectangle of size h×w
.
A rectangle of size h×w
is a rectangle consisting of h rows and w columns such that its top left corner is at a cell (a,b) and its right bottom corner is at a cell (c,d), and the following conditions are satisfied: (c−a+1≡h) and (d−b+1≡w
).
The median of a set of numbers is the middle element in the sorted list of the given set. For example, the median of {2,1,3}
is 2 and the median of {4,2,3,1,5} is 3
.
Input
The first line contains four integers n
, m, h, and w (1≤n,m≤103, 1≤h,w≤n), in which n and m are the number of rows and columns in the grid, respectively, and h and w are representing the size of the required rectangle. Both h and w
are odd integers.
Then n
lines follow, each line contains n integers, giving the grid. It is guaranteed that the grid contains unique values between 1 and n×m
(inclusive).
Output
Print a single line containing the smallest median value that can be found in a rectangle of size h×w
.
Example
Input
4 4 3 3 13 16 15 4 5 2 8 9 14 11 12 10 1 6 3 7
Output
6
Note
In the first test case, there are 4
possible rectangles of size 3×3
, which are:
- Starts at (1,1
). → Contains elements: {13,16,15,5,2,8,14,11,12}. → Median value = 12
- .
- Starts at (1,2
- ). → Contains elements: {16,15,4,2,8,9,11,12,10}. → Median value = 10
- .
- Starts at (2,1
- ). → Contains elements: {5,2,8,14,11,12,1,6,3}. → Median value = 6
- .
- Starts at (2,2
- ). → Contains elements: {2,8,9,11,12,10,6,3,7}. → Median value = 8
- .
So, the smallest median value that can be found in a rectangle of size 3×3
is 6.
题解:二分答案,先开一个数组copy原数组与答案的大小关系,比答案小于等于为1,否则为0,然后进行矩阵前缀和,然后枚举所有的h*w小矩阵,如果这个小矩阵中1的个数比答案多的话就说明答案可以更小,否则答案需要更大。
#include<bits/stdc++.h>
using namespace std;
const int maxn=1010;
int n,m,w,h,flag,ans,l,r,mid;
int a[maxn][maxn];
int v[maxn][maxn];
bool ok(int x)
{
memset(v,0,sizeof(v));
for(int i=1;i<=n;i++)
{
for(int j=1;j<=m;j++)
{
if(a[i][j]<=x)//标记比x小的个数
v[i][j]=1;
}
}
for(int i=1;i<=n;i++)//矩阵前缀和
{
for(int j=1;j<=m;j++)
{
v[i][j]+=v[i-1][j]+v[i][j-1]-v[i-1][j-1];
}
}
for(int i=1;i<=n-h+1;i++)//枚举每个小矩形
{
for(int j=1;j<=m-w+1;j++)
{
int r=v[i+h-1][j+w-1]-v[i-1][j+w-1]-v[i+h-1][j-1]+v[i-1][j-1];
if(r>=flag)
return 1;
}
}
return 0;
}
int main()
{
std::ios::sync_with_stdio(0);
cin>>n>>m>>h>>w;
for(int i=1;i<=n;i++)
{
for(int j=1;j<=m;j++)
{
cin>>a[i][j];
}
}
l=1,r=n*m,flag=w*h/2+1;//w*h个数中相对中位数为w*h/2+1
while(l<=r)//二分答案
{
mid=(l+r)/2;
if(ok(mid))
ans=mid,r=mid-1;
else
l=mid+1;
}
cout<<ans<<endl;
return 0;
}