1047: [HAOI2007]理想的正方形

Time Limit: 10 Sec  Memory Limit: 162 MB
Submit: 4075  Solved: 2277
[Submit][Status][Discuss]

Description

  有一个a*b的整数组成的矩阵,现请你从中找出一个n*n的正方形区域,使得该区域所有数中的最大值和最小值
的差最小。

Input

  第一行为3个整数,分别表示a,b,n的值第二行至第a+1行每行为b个非负整数,表示矩阵中相应位置上的数。每
行相邻两数之间用一空格分隔。
100%的数据2<=a,b<=1000,n<=a,n<=b,n<=1000

Output

  仅一个整数,为a*b矩阵中所有“n*n正方形区域中的最大整数和最小整数的差值”的最小值。

Sample Input

5 4 2
1 2 5 6
0 17 16 0
16 17 2 1
2 10 2 1
1 2 2 2

Sample Output

1

二维单调队列

先计算每行前n个点的最大值和最小值,用单调队列维护。

然后按列的顺序计算每个点作为右下角时,矩阵的最大值和最小值。

简单来说,就是多次运用单调队列,将二维矩阵压缩为一维矩阵求解

 1 #include<iostream>
 2 #include<cstdio>
 3 using namespace std;
 4
 5 const int MAXN=1000+5;
 6 const int INF=0x7fffffff;
 7
 8 int a,b,n,ans=INF;
 9 int s[MAXN][MAXN],mx[MAXN][MAXN],mn[MAXN][MAXN];
10 int val[MAXN],pos[MAXN],x[MAXN],y[MAXN];
11
12 int main()
13 {
14     scanf("%d %d %d",&a,&b,&n);
15     for(int i=1;i<=a;i++)
16         for(int j=1;j<=b;j++)
17             scanf("%d",&s[i][j]);
18     int l,r;
19     for(int i=1;i<=a;i++)
20     {
21         l=1,r=1;
22         for(int j=1;j<=b;j++)
23         {
24             while(l<r&&val[r-1]<=s[i][j]) r--;
25             val[r]=s[i][j];pos[r]=j;r++;
26             if(pos[l]==j-n) l++;
27             if(j>=n) mx[i][j]=val[l];
28         }
29         l=1,r=1;
30         for(int j=1;j<=b;j++)
31         {
32             while(l<r&&val[r-1]>=s[i][j]) r--;
33             val[r]=s[i][j];pos[r]=j;r++;
34             if(pos[l]==j-n) l++;
35             if(j>=n) mn[i][j]=val[l];
36         }
37     }
38     for(int i=n;i<=b;i++)
39     {
40         l=1,r=1;
41         for(int j=1;j<=a;j++)
42         {
43             while(l<r&&val[r-1]<=mx[j][i]) r--;
44             val[r]=mx[j][i];pos[r]=j;r++;
45             if(pos[l]==j-n) l++;
46             if(j>=n) x[j]=val[l];
47         }
48         l=1,r=1;
49         for(int j=1;j<=a;j++)
50         {
51             while(l<r&&val[r-1]>=mn[j][i]) r--;
52             val[r]=mn[j][i];pos[r]=j;r++;
53             if(pos[l]==j-n) l++;
54             if(j>=n) y[j]=val[l];
55         }
56         for(int i=n;i<=a;i++) ans=min(ans,x[i]-y[i]);
57     }
58     printf("%d\n",ans);
59     return 0;
60 }

原文地址:https://www.cnblogs.com/InWILL/p/9337841.html

时间: 2024-08-02 18:05:03

1047: [HAOI2007]理想的正方形的相关文章

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]理想的正方形(单调队列/~二维rmq+树状数组套树状数组)

http://www.lydsy.com/JudgeOnline/problem.php?id=1047 树状数组套树状数组真心没用QAQ....首先它不能修改..而不修改的可以用单调队列做掉,而且更快,只有O(n^2).而这货是n^2log^2n的建树...虽然查询是log^2n...但是建树那里就tle了.. 那么说题解... 先orz下,好神.. 我怎么没想到单调队列orz 首先我们维护 行 的单调队列,更新每个点在 列 距离内的最小and最大的值 然后我们维护 列 的单调队列,更新每个点

1047: [HAOI2007]理想的正方形——二维单调队列

http://www.lydsy.com/JudgeOnline/problem.php?id=1047 对每一行维护一个单调队列,保存在lmin[][],lmax[][] 然后对每一列维护一个单调队列,最后n*n枚举 #include <iostream> #include <cstring> #include <cstdio> #include <algorithm> #define clr(a,b) memset(a,b,sizeof(a)) cons

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

题目大意:给定一个a*b的矩阵,求一个n*n的子矩阵,使矩阵中的最大值与最小值之差最小 对于每行维护一个单调递减的队列.再弄一个竖着的队列.维护n个格子之内的最大值就可以 两遍统计出最大值和最小值 然后得到ans就可以 #include<cstdio> #include<cstring> #include<iostream> #include<algorithm> #define M 1010 using namespace std; struct abcd

bzoj 1047: [HAOI2007]理想的正方形【单调队列】

没有复杂结构甚至不长但是写起来就很想死的代码类型 原理非常简单,就是用先用单调队列处理出mn1[i][j]表示i行的j到j+k-1列的最小值,mx1[i][j]表示i行的j到j+k-1列的最大值 然后就变成求单列最大最小值,用上面同样的方法处理出对于列的mn2mx2即可 #include<iostream> #include<cstdio> using namespace std; const int N=1005; int n,m,k,a[N][N],mn1[N][N],mx1[

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

[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