Gym 102152L

题意:
给一个 n ∗ m n*m nm矩阵数组,让求子矩阵大小为 h ∗ w h*w hw的最小中位数,确保 n ∗ m n*m nm为奇数。

思路:
二分+求二维数组的前缀和。
二分答案x,然后判断二维矩阵中那个大于x的位置为1,然后二维矩阵的前缀和,二分大于x的数量,若子矩阵中有数量大于 ( h ∗ w + 1 ) / 2 (h*w+1)/2 (hw+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--)
    // {

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值