题意:
给一个
n
∗
m
n*m
n∗m矩阵数组,让求子矩阵大小为
h
∗
w
h*w
h∗w的最小中位数,确保
n
∗
m
n*m
n∗m为奇数。
思路:
二分+求二维数组的前缀和。
二分答案x,然后判断二维矩阵中那个大于x的位置为1,然后二维矩阵的前缀和,二分大于x的数量,若子矩阵中有数量大于
(
h
∗
w
+
1
)
/
2
(h*w+1)/2
(h∗w+1)/2则缩小,反则扩大。
参考代码:
/*
* @Author: vain
* @Date: 2020-08-26 11:58:46
* @LastEditTime: 2020-09-10 19:04:49
* @LastEditors: sueRimn
* @Description: In User Settings Edit
* @FilePath: \main\demo.cpp
*/
//#include <bits/stdc++.h>
#include <cstdio>
#include <algorithm>
#include <iostream>
#include <vector>
#include <map>
#include <queue>
#include <set>
#include <ctime>
#include <cstring>
#include <cstdlib>
#include <math.h>
#include <bitset>
using namespace std;
typedef long long ll;
//#define ll long long
typedef unsigned long long ull;
const int N = 1e3 + 20;
const ll maxn = 1e5 + 20;
const ll mod = 1e9 + 7;
ll head[maxn], stac[maxn];
int a[maxn], b[maxn], c[maxn];
//typedef pair<ll, ll> p;
//priority_queue<p, vector<p>, greater<p> > m;
//ll sum[maxn];
int max(int a, int b) { return a > b ? a : b; }
ll min(ll a, ll b) { return a < b ? a : b; }
ll gcd(ll a, ll b) { return b ? gcd(b, a % b) : a; }
ll lcm(ll a, ll b) { return a * b / gcd(a, b); }
void swap(ll &x, ll &y) { x ^= y, y ^= x, x ^= y; }
map<string, ll> pll, che, mp;
int ik[N], q[N], cnt;
int lowbit(int x) { return (x) & (-x); }
vector<int> fc;
//ull h[maxn], p[maxn];
const ull base = 13331;
//char s1[maxn];
ll ksm(ll a, ll b)
{
ll res = 1;
while (b)
{
if (b & 1)
res = a * res;
b >>= 1;
a = a * a;
}
return res;
}
int f[N][N], solv[N][N], stk[N];
int get(int x)
{
int ans = 0;
while (x)
{
if (x & 1)
ans++;
x >>= 1;
}
return ans;
}
void init(int x, int n, int m)
{
for (int i = 1; i <= n; i++)
{
for (int j = 1; j <= m; j++)
{
if (f[i][j] <= x)
solv[i][j] = 1;
else
solv[i][j] = 0;
}
}
for (int i = 1; i <= n; i++)
{
for (int j = 1; j <= m; j++)
{
solv[i][j] = solv[i][j - 1] + solv[i - 1][j] - solv[i - 1][j - 1] + solv[i][j];
}
}
}
bool check(int x, int n, int m, int h, int w)
{
init(x, n, m);
for (int i = h; i <= n; i++)
{
for (int j = w; j <= m; j++)
{
int ans = solv[i][j] - solv[i][j - w] - solv[i - h][j] + solv[i - h][j - w];
if (ans >= (h * w + 1) / 2)
return true;
}
}
return false;
}
int main()
{
ios::sync_with_stdio(false);
cin.tie(0), cout.tie(0);
srand(time(NULL));
//cout << ksm(2, 20) << endl;
int n, m, t, s, q, h, w;
cin >> n >> m >> h >> w;
for (int i = 1; i <= n; i++)
{
for (int j = 1; j <= m; j++)
{
cin >> f[i][j];
}
}
int l = 1, r = n * m, ans = 0;
while (l <= r)
{
int mid = l + r >> 1;
if (check(mid, n, m, h, w))
{
ans = mid, r = mid - 1;
}
else
l = mid + 1;
}
cout << ans << endl;
// cin >> t;zz
// while (t--)
// {
// }
}