bzoj1047理想的正方形

题目地址: bzoj1047
我好菜啊qwq,这道题调了一万年
n = 1000 理论上可以用数据结构水过去,,,但是我太菜了不会qwq
做法差不多就是先维护在某一行的连续n个数的最值,用g[i][j]表示,在这个基础上维护以某个点为右下角的n * n 的矩形内的最值,用f[i][j]表示。
就……完了
min 和 max 分别维护一下就好了
然而这破题还是调了快1个小时qwq
//gdb真好用辣鸡dev老是炸
代码:

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <climits>
using namespace std;

const int MAXN = 1000 + 10;

int a, b, n;
int map[MAXN][MAXN];

int q1[MAXN], q2[MAXN], l(1), r(0);
int fmx[MAXN][MAXN], fmn[MAXN][MAXN];
int gmx[MAXN][MAXN], gmn[MAXN][MAXN];

void solve_mx() {
    for (int i=1; i<=a; ++i) {
        l = 1, r = 0;
        for (int j=1; j<=b; ++j) {
            while (l <= r && q1[r] <= map[i][j]) -- r;
            ++ r;
            q1[r] = map[i][j], q2[r] = j;
            while (l <= r && j - q2[l] + 1 > n) ++ l;
            gmx[i][j] = q1[l];
        }
    }

    for (int j=1; j<=b; ++j) {
        l = 1, r = 0;
        for (int i=1; i<=a; ++i) {
            while (l <= r && q1[r] <= gmx[i][j]) -- r;
            ++ r;
            q1[r] = gmx[i][j], q2[r] = i;
            while (l <= r && i - q2[l] + 1 > n) ++ l;
            fmx[i][j] = q1[l];
        }
    }
}

void solve_mn() {
    for (int i=1; i<=a; ++i) {
        l = 1, r = 0;
        for (int j=1; j<=b; ++j) {
            while (l <= r && q1[r] >= map[i][j]) -- r;
            ++ r;
            q1[r] = map[i][j], q2[r] = j;
            while (l <= r && j - q2[l] + 1 > n) ++ l;
            gmn[i][j] = q1[l];
        }
    }

    for (int j=1; j<=b; ++j) {
        l = 1, r = 0;
        for (int i=1; i<=a; ++i) {
            while (l <= r && q1[r] >= gmn[i][j]) -- r;
            ++ r;
            q1[r] = gmn[i][j], q2[r] = i;
            while (l <= r && i - q2[l] + 1 > n) ++ l;
            fmn[i][j] = q1[l];
        }
    }
}

int main() {
    ios::sync_with_stdio(0);
    cin >> a >> b >> n;
    for (int i=1; i<=a; ++i) {
        for (int j=1; j<=b; ++j) {
            cin >> map[i][j];
        }
    }
    solve_mx();
    solve_mn();
    int ans = INT_MAX;
    for (int i=n; i<=a; ++i) {
        for (int j=n; j<=b; ++j) {
            ans = min(ans, fmx[i][j] - fmn[i][j]);
        }
    }

    cout << ans;
}

我好菜啊qwq

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值