【BZOJ 1047】理想的正方形

本文介绍了一种使用二维单调队列来维护二维数组最大值和最小值的方法,并提供了完整的实现代码。通过先处理行再处理列的方式,可以高效地解决特定问题。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

题目来源:BZOJ 1047

思路:

用二维单调队列维护二维数组的最大值和最小值,之后直接查询。
具体的来说,先用单调队列维护每一行的值,再维护每一列的值。

代码:

#include <cstdio>
#include <iostream>
#include <algorithm>
using namespace std;
inline int gt(){
    char c = ' ';
    int num = 0, op = 1, ok = 0;
    while(1){
        c = getchar();
        if(c == '-') op = -1;
        if(c <= '9' && c >= '0') num = num * 10 + c  - '0', ok = 1;
        else if(ok) return op * num;
    }
}
int a1[1010][1010], a2[1010][1010], a3[1010][1010];
int a4[1010][1010], a5[1010][1010];
int a, b, n, res = 2e9;
int q1[1010], l, r;
int main(){
    scanf("%d%d%d", &a, &b, &n);
    for(int i = 1; i <= a; i ++)
        for(int j = 1; j <= b; j ++)
            a1[i][j] = gt();
    for(int i = 1; i <= a; i ++){
        l = 1, r = 0;
        for(int j = 1; j <= b; j ++){
            while(r >= l && j - q1[l] >= n) l ++;
            while(r >= l && a1[i][j] >= a1[i][q1[r]]) r --;
            q1[++r] = j;
            a2[i][j] = a1[i][q1[l]];
        }
        l = 1, r = 0;
        for(int j = 1; j <= b; j ++){
            while(r >= l && j - q1[l] >= n) l ++;
            while(r >= l && a1[i][j] <= a1[i][q1[r]]) r --;
            q1[++r] = j;
            a3[i][j] = a1[i][q1[l]];
        }
    }
    for(int i = 1; i <= b; i ++){
        l = 1, r = 0;
        for(int j = 1; j <= a; j ++){
            while(r >= l && j - q1[l] >= n) l ++;
            while(r >= l && a2[j][i] >= a2[q1[r]][i]) r --;
            q1[++r] = j;
            a4[j][i] = a2[q1[l]][i];
        }
        l = 1, r = 0;
        for(int j = 1; j <= a; j ++){
            while(r >= l && j - q1[l] >= n) l ++;
            while(r >= l && a3[j][i] <= a3[q1[r]][i]) r --;
            q1[++r] = j;
            a5[j][i] = a3[q1[l]][i];
        }
    }
    for(int i = n; i <= a; i ++)
        for(int j = n; j <= b; j ++)
            if(a4[i][j] - a5[i][j] < res) res = a4[i][j] - a5[i][j];
    printf("%d", res);
    return 0;
} 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值