BZOJ 1047 理想的正方形

       看到这到题,第一反应当然是暴搜一遍,但是数据较大,暴搜铁定过不了,自然想到进行优化,优化的方案很多,每个人的思路可能不同,在这里我的思路仅供参考。

        我的想法是用单调队列、单调栈,当然简单的单调队列、单调栈只适用于一行数据,对于这道题要进行一定的组合和变换。根据题目的介绍,可以大致总结出以下信息:第一,矩阵由b组长度为a的数列组成;第二,求的范围是m*m。因而,我们可以先取第一行进行考虑,简单的理解为依次输入每一个数据,输入一个求取一下后m个数据中的最大值,并将之记录进一个新建数组,求取过程就是最裸的单调队列、单调栈,将每一行进行求值得到了一组新数据,这组数据记录了原数据横向上每m个中的最大值,也就是m*m方阵中每行的最大值,再将数据按竖着的方向进行上述操作,输入一个求一次后m个中的最大值,这样得到的就是最终结果。(如果有不理解的,请看下图)

题目的大致程序如下:

#include <iostream>
#include <cstring>
#include <cstdio>
#include <algorithm>
#include <cstdlib>
#define inf 0x3f3f3f3f

using namespace std;

int i_long,i_wide,i_side;
int g[1005][1005],f[1005][1005][2],t[1005][1005];
struct qu
{
    int i_value,p;
}q[1005];

void Getgf(int k)
{
    for (int j=1;j<=i_wide;j++)
    {
        int l=1,r=0;
        for (int i=1;i<=i_long;i++)
        {
            while (r&&r>=l&&t[i][j]<=q[r].i_value) r--;
            while (l&&l<=r&&q[l].p<=i-i_side) l++;

            q[++r].i_value=t[i][j];
            q[r].p=i;
            g[i][j]=q[l].i_value;
        }
    }
    for (int i=i_side;i<=i_long;i++)
    {
        int l=1,r=0;
        for (int j=1;j<=i_wide;j++)
        {
            while (r&&r>=l&&g[i][j]<=q[r].i_value) r--;
            while (l&&l<=r&&q[l].p<=j-i_side) l++;

            q[++r].i_value=g[i][j];
            q[r].p=j;
            f[i][j][k]=q[l].i_value;
        }
    }
}

int main()
{
    scanf("%d%d%d",&i_long,&i_wide,&i_side);
    for (int i=1;i<=i_long;i++)
    {
        for (int j=1;j<=i_wide;j++)
        {
            scanf("%d",&t[i][j]);
         }
    }

    Getgf(0);

    for (int i=1;i<=i_long;i++)
    {
        for (int j=1;j<=i_wide;j++)
        {
            t[i][j]=-t[i][j];
        }
    }

    Getgf(1);

    int ans=inf;
    for (int i=i_side;i<=i_long;i++)
    {
        for (int j=i_side;j<=i_wide;j++)
        {
            ans=min(ans,-f[i][j][1]-f[i][j][0]);
        }
    }

    cout<<ans<<endl;

    return 0;
}

希望所写内容对您有所帮助,谢谢。

时间: 2025-01-13 20:24:18

BZOJ 1047 理想的正方形的相关文章

[BZOJ]1047 理想的正方形(HAOI2007)

真·水题.小C本来是不想贴出来的,但是有一股来自东方的神秘力量催促小C发出来. Description 有一个a*b的整数组成的矩阵,现请你从中找出一个n*n的正方形区域,使得该区域所有数中的最大值和最小值的差最小. Input 第一行为3个整数,分别表示a,b,n的值第二行至第a+1行每行为b个非负整数,表示矩阵中相应位置上的数.每行相邻两数之间用一空格分隔. Output 仅一个整数,为a*b矩阵中所有“n*n正方形区域中的最大整数和最小整数的差值”的最小值. Sample Input 5

BZOJ 1047 理想的正方形(单调队列)

刚开始用二维RMQ直接给超内存了... 用单调队列可以做到O(n^2)的复杂度.具体是先把每行用单调队列处理一下.再把处理后的用列单调队列处理下. # include <cstdio> # include <cstring> # include <cstdlib> # include <iostream> # include <vector> # include <queue> # include <stack> # in

BZOJ [HAOI2007]理想的正方形

题解:思路,二维转一维: 先求每一行相邻k个的最值 然后相邻k个看成整体竖着再求一遍 用单调队列实现 #include<iostream> #include<cstdio> #include<cstring> using namespace std; const int maxn=1009; int n,m,k; int ans=1000000000; int a[maxn][maxn]; int mn[maxn][maxn]; int mx[maxn][maxn];

【BZOJ 1047】 [HAOI2007]理想的正方形

1047: [HAOI2007]理想的正方形 Time Limit: 10 Sec  Memory Limit: 162 MB Submit: 1685  Solved: 891 [Submit][Status] Description 有一个a*b的整数组成的矩阵,现请你从中找出一个n*n的正方形区域,使得该区域所有数中的最大值和最小值的差最小. Input 第一行为3个整数,分别表示a,b,n的值第二行至第a+1行每行为b个非负整数,表示矩阵中相应位置上的数.每行相邻两数之间用一空格分隔.

BZOJ 1047 [HAOI2007]理想的正方形

[看了题解才会做 这是一个典型的二维滑动窗口问题~ 二维滑动窗口问题的处理方法可以类比一维滑动窗口的处理方法 首先将矩阵分解成B个列,对这B个列分别用单调队列维护一个长度为N的一维滑动窗口.记录colmax[i][j]为第j列第i行的元素(即第j个列的第i个元素)到第j列第i-N+1的元素(即第j个列的第i-N+1个元素)的最大值.这个用单调队列随便维护一下就好啦~ 然后将矩阵分解成A个行,对这A个行再分别用单调队列维护一个长度为N的一维滑动窗口.记录rowmax[i][j]为colmax[i]

【BZOJ】【1047】【HAOI2007】理想的正方形

DP/单调队列优化 一眼看上去就是DP 我想的naive的二维DP是酱紫滴: mx[i][j][k]表示以(i,j)为右下角的k*k的正方形区域内的最大值,mn[i][j][k]同理 mx[i][j][k]=max(v[i][j],max(v[i-k+1][j-k+1],max(mx[i-1][j][k-1],mx[i][j-1][k-1]))),mn[i][j][k]同理 这个DP是既爆空间又爆时间的……我把空间优化了一下:由于转移的时候只用到了i-1行的DP值,所以可以用滚动数组. 但是时间

[BZOJ1047][HAOI2007]理想的正方形

1047: [HAOI2007]理想的正方形 Time Limit: 10 Sec  Memory Limit: 162 MB Submit: 3481  Solved: 1917 [Submit][Status][Discuss] Description 有一个a*b的整数组成的矩阵,现请你从中找出一个n*n的正方形区域,使得该区域所有数中的最大值和最小值 的差最小. Input 第一行为3个整数,分别表示a,b,n的值第二行至第a+1行每行为b个非负整数,表示矩阵中相应位置上的数.每 行相邻

RAM——[HAOI2007]理想的正方形

题目:[HAOI2007]理想的正方形 描述: [问题描述] 有一个a*b的整数组成的矩阵,现请你从中找出一个n*n的正方形区域,使得该区域所有数中的最大值和最小值的差最小. [输入]: 第一行为3个整数,分别表示a,b,n的值 第二行至第a+1行每行为b个非负整数,表示矩阵中相应位置上的数.每行相邻两数之间用一空格分隔. [输出]: 仅一个整数,为a*b矩阵中所有“n*n正方形区域中的最大整数和最小整数的差值”的最小值. [输入样例] 5 4 2 1 2 5 6 0 17 16 0 16 17

HAOI2007 理想的正方形 单调队列

单调队列 by   GeneralLiu 滑动窗口是比较裸的单调队列 理想的正方形   就拔高了一个层次(多了一维) 有一个a*b的整数组成的矩阵 现请你从中找出一个n*n的正方形区域 使得该区域所有数中的最大值和最小值的差最小 只写MAX了,MIN一个道理,懒 不写了 先横着跑单调队列 维护许多长度为 n 的 横着的MAX 存在数组 map1[][] 中 再对数组 map1[][] 竖着跑单调队列 就维护了 许多 n*n 的 矩阵的MAX MIN同理 在竖着跑单调队列时 顺便MAX 与 MIN