bzoj1047理想的正方形

题目链接

纪念又双叒叕的一道暴力碾标算的题

我们考虑纯暴力

#include<iostream>
#include<cstdio>
#include<algorithm>
using namespace std;
int a,b,n;
int map[1010][1010];
int ans=0x3f3f3f3f;
int main()
{
 scanf("%d%d%d",&a,&b,&n);
 for(int i=1;i<=a;i++)
   for(int j=1;j<=b;j++)
  scanf("%d",&map[i][j]);
    for(int i=1;i+n-1<=a;i++)
      for(int j=1;j+n-1<=b;j++){
  int maxx=0,minn=0x3f3f3f3f;
     for(int l=i;l<=n+i-1;l++)
          for(int r=j;r<=n+j-1;r++)
            maxx=max(maxx,map[l][r]),
            minn=min(minn,map[l][r]);
  ans=min(ans,maxx-minn);
    }
    printf("%d",ans);
    return 20020902;
}

然后显然,果断$TLE$

呵呵呵

那么我们考虑怎么优化暴力

别跟我提什么数据结构啊,单调队列

本小可爱一个也不会

我们回头看看这两道题 洛谷P2038洛谷P2280

这两道题也是矩阵,然后我们是用的维护二维前缀和来找的在一个矩形内的某些数值

那么,这道题是不是也可以类似的做呢?

由于询问的都是正方形,

我们可以预处理出来

所有正方形的最大最小值

($ps:$从$(1,1)$开始计数)

定义$maxx[i][j][k]$表示以$(i,j)$为左上端点,然后边长为$k$的正方形最大值,$minn[i][j][k]$表示最小。

通过类比上两道题,还有画图,得出

$$maxx[i][j][k]=max(max(maxx[i][j][k-1],maxx[i+1][j+1][k-1]),max(maxx[i][j+1][k-1],maxx[i+1][j][k-1]))$$

$$minn[i][j][k]=min(min(minn[i][j][k-1],minn[i+1][j+1][k-1]),min(minn[i][j+1][k-1],minn[i+1][j][k-1]))$$

所以,我们可以求出来$maxx[][][n],minn[][][n]$

然后枚举左上角端点然后更新答案就行


别以为这样就好了

您写完了之后本地编译了么?

是不是编译未成功?

因为$maxx,minn$这样要开$1001*1001*1001=1e9$辣么大的数组

显然开不下啊$qwq$

那怎么办?

凉拌啊!

发现我们推$maxx,minn$的时候,每次只涉及到$k,k-1$,并且只涉及到$i+1,j+1,i,j$这几个东东,所以可以类似滚动数组优化,滚掉$k$这一维

然后又是省选题

开个$O2$也没什么大不了的

其实是本宝宝懒得写优化了

上代码:

看,连$1kb$都不到

真是暴力碾标算的好题啊$qwq$

// luogu-judger-enable-o2
#pragma GCC optimize (2)
#include<iostream>
#include<cstdio>
#include<algorithm>
using namespace std;
int a,b,n;
int map[1010][1010];
int maxx[1010][1010];
int minn[1010][1010];
int ans=0x3f3f3f3f;
int main()
{
    scanf("%d%d%d",&a,&b,&n);
    for(int i=1;i<=a;i++)
      for(int j=1;j<=b;j++)
        scanf("%d",&map[i][j]),
        maxx[i][j]=minn[i][j]=map[i][j];
    for(int k=2;k<=n;k++)
      for(int i=1;i+k<=a+1;i++)
        for(int j=1;j+k<=b+1;j++)
          maxx[i][j]=max(max(maxx[i][j],maxx[i+1][j+1]),max(maxx[i][j+1],maxx[i+1][j])),
          minn[i][j]=min(min(minn[i][j],minn[i+1][j+1]),min(minn[i][j+1],minn[i+1][j])),
          ans=k==n?min(ans,maxx[i][j]-minn[i][j]):0x3f3f3f3f;
    printf("%d",ans);
    return 0;
}
/*
5   4   2
1   2   5   6
0   17  16  0
16  17  2   1
2   10  2   1
1   2   2   2
*/

原文地址:https://www.cnblogs.com/cn-suqingnian/p/9412851.html

时间: 2024-10-31 22:13:38

bzoj1047理想的正方形的相关文章

[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个非负整数,表示矩阵中相应位置上的数.每 行相邻

【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个非负整数,表示矩阵中相应位置上的数.每行相邻两数之间用一空格分隔.

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

【HAOI2007】理想的正方形

[问题描述] 有一个a*b的整数组成的矩阵,现请你从中找出一个n*n的正方形区域,使得该区域所有数中的最大值和最小值的差最小. [输入] 第一行为3个整数,分别表示a,b,n的值第二行至第a+1行每行为b个非负整数,表示矩阵中相应位置上的数.每行相邻两数之间用一空格分隔. [输出] 仅一个整数,为a*b矩阵中所有"n*n正方形区域中的最大整数和最小整数的差值"的最小值. [分析] 单调队列,先处理横行,再处理竖行. 1 #include <cstdlib> 2 #inclu

一本通1604理想的正方形

1604:理想的正方形 时间限制: 1000 ms         内存限制: 524288 KB [题目描述] 原题来自:HAOI 2007 有一个 a×b 的整数组成的矩阵,现请你从中找出一个 n×n 的正方形区域,使得该区域所有数中的最大值和最小值的差最小. [输入] 第一行为三个整数,分别表示 a,b,n 的值: 第二行至第 a+1 行每行为 b 个非负整数,表示矩阵中相应位置上的数. [输出] 输出仅一个整数,为 a×b 矩阵中所有「n×n 正方形区域中的最大整数和最小整数的差值」的最

【bzoj1047】[HAOI2007]理想的正方形 二维RMQ

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

[BZOJ1047] [HAOI2007] 理想的正方形 (单调队列)

Description 有一个a*b的整数组成的矩阵,现请你从中找出一个n*n的正方形区域,使得该区域所有数中的最大值和最小值的差最小. Input 第一行为3个整数,分别表示a,b,n的值第二行至第a+1行每行为b个非负整数,表示矩阵中相应位置上的数.每行相邻两数之间用一空格分隔.100%的数据2<=a,b<=1000,n<=a,n<=b,n<=100 Output 仅一个整数,为a*b矩阵中所有“n*n正方形区域中的最大整数和最小整数的差值”的最小值. Sample In

【单调队列】bzoj1047 [HAOI2007]理想的正方形

先把整个矩阵处理成b[n][m-K+1].c[n][m-K+1]大小的两个矩阵,分别存储每行每K个数中的最大.最小值,然后再通过b.c处理出d.e分别表示K*K大小的子矩阵中的最大.最小值即可.单调队列暴力. #include<cstdio> #include<algorithm> using namespace std; #define N 1001 int n,m,K,a[N][N],b[N][N],c[N][N],q[N],head,tail,d[N][N],e[N][N];