L - Median (矩阵前缀和+二分)

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:

  1. 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
    1. .

    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;
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值