题目
给出一个二维数组,求固定大小方块间的最小的中值,数据范围为n<1000
思路
方块大小固定,那么比中值小的数的个数可确定,对数组中符合的方块判断是否符合个数,二分解决,个数多了即答案更小,等于时向下寻找,小于时答案更大
对于个数的判断,使用计数数组,将counts[i][j]定义为从(1,1)到(i,j)的小于等于中值的个数,得到数组后遍历判断即可
代码
#include <iostream>
using namespace std;
int n,m,h,w,s;
int arr[1005][1005]={0};
int counts[1005][1005]={0};
int judge(int x)
{
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
{
if(arr[i][j]<=x) counts[i][j]=1;
else counts[i][j]=0;
}
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
counts[i][j]+=(counts[i-1][j]+counts[i][j-1]-counts[i-1][j-1]);
int k=0;
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
{
if(i+h-1>n||j+w-1>m) continue;
k=max(k,counts[i+h-1][j+w-1]+counts[i-1][j-1]-counts[i-1][j+w-1]-counts[i+h-1][j-1]);
}
if(k>=s) return -1;
else return 0;
}
int main()
{
scanf("%d%d%d%d",&n,&m,&h,&w);
s=h*w/2+1;
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
scanf("%d",arr[i]+j);
int l=1,r=n*m,ans;
while(l<=r)
{
int mid=(l+r)/2;
int res=judge(mid);
if(res==-1) r=mid-1,ans=mid;
else l=mid+1;
}
printf("%d",ans);
return 0;
}