题目链接:BZOJ - 1047

题目分析

使用单调队列在 O(n^2) 的时间内求出每个 n * n 正方形的最大值,最小值。然后就可以直接统计答案了。

横向有 a 个单调队列(代码中是 Q[1] 到 Q[a] ),维护每行当前枚举区间的单调队列。

纵向一个单调队列(代码中是 Q[0] ),求出当前枚举区间的每行的单调队列后,就得到了每行的这个区间的最小值(最大值),就相当于一个长度为行数的数组,然后纵向做单调队列,求出的就是正方形的最值了。

代码

#include <iostream>
#include <cstdlib>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>using namespace std;const int MaxN = 1000 + 5, INF = 999999999;int a, b, n, Ans;
int Map[MaxN][MaxN], Q[MaxN][MaxN], F[MaxN], Head[MaxN], Tail[MaxN], Min[MaxN][MaxN], Max[MaxN][MaxN];
//Q[0]是纵向的单调队列 inline int gmin(int a, int b) {return a < b ? a : b;}
inline int gmax(int a, int b) {return a > b ? a : b;}void Get_Min()
{for (int i = 1; i <= a; ++i) {Head[i] = 1;Tail[i] = 0;}for (int i = 1; i <= b; ++i) {for (int j = 1; j <= a; ++j) {if (i > n && Head[j] <= Tail[j] && Q[j][Head[j]] == i - n) ++Head[j];while (Head[j] <= Tail[j] && Map[j][i] < Map[j][Q[j][Tail[j]]]) --Tail[j];Q[j][++Tail[j]] = i; }   if (i >= n) {Head[0] = 1; Tail[0] = 0;for (int j = 1; j <= a; ++j){F[j] = Map[j][Q[j][Head[j]]];if (j > n && Head[0] <= Tail[0] && Q[0][Head[0]] == j - n) ++Head[0];while (Head[0] <= Tail[0] && F[j] < F[Q[0][Tail[0]]]) --Tail[0];Q[0][++Tail[0]] = j;if (j >= n) Min[j][i] = F[Q[0][Head[0]]]; }}}
}void Get_Max()
{for (int i = 1; i <= a; ++i) {Head[i] = 1;Tail[i] = 0;}for (int i = 1; i <= b; ++i) {for (int j = 1; j <= a; ++j) {if (i > n && Head[j] <= Tail[j] && Q[j][Head[j]] == i - n) ++Head[j];while (Head[j] <= Tail[j] && Map[j][i] > Map[j][Q[j][Tail[j]]]) --Tail[j];Q[j][++Tail[j]] = i; }if (i >= n) {Head[0] = 1; Tail[0] = 0;for (int j = 1; j <= a; ++j){F[j] = Map[j][Q[j][Head[j]]];if (j > n && Head[0] <= Tail[0] && Q[0][Head[0]] == j - n) ++Head[0];while (Head[0] <= Tail[0] && F[j] > F[Q[0][Tail[0]]]) --Tail[0];Q[0][++Tail[0]] = j;if (j >= n) Max[j][i] = F[Q[0][Head[0]]]; }}}
}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]);Get_Min();Get_Max();Ans = INF;for (int i = n; i <= a; ++i) for (int j = n; j <= b; ++j) Ans = gmin(Ans, Max[i][j] - Min[i][j]);printf("%d\n", Ans);return 0;
}

  

转载于:https://www.cnblogs.com/JoeFan/p/4319732.html

[BZOJ 1047] [HAOI2007] 理想的正方形 【单调队列】相关推荐

  1. BZOJ 1047: [HAOI2007]理想的正方形 单调队列瞎搞

    题意很简明吧? 枚举的矩形下边界和右端点即右下角,来确定矩形位置: 每一个纵列开一个单调队列,记录从 i-n+1 行到 i 行每列的最大值和最小值,矩形下边界向下推移的时候维护一下: 然后在记录的每一 ...

  2. bzoj 1047: [HAOI2007]理想的正方形

    1047: [HAOI2007]理想的正方形 Time Limit: 10 Sec  Memory Limit: 162 MB Submit: 3324  Solved: 1828 [Submit][ ...

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

    题目链接 Solution MD,经过这道题,算是掌握单调队列了... 可以先预处理出点 \((i,j)\) 往上 \(n\) 的最大值和最小值. 然后再横着做一遍单调队列即可. Code #incl ...

  4. bzoj1047 [HAOI2007]理想的正方形 单调队列

    这种在矩形里面找矩形有固定的套路,不是容斥就是左右上下延伸,这个题就是向左向右延伸.. 然后手玩优化发现邻位转移比暴力要好一些,可以用splay统计,但复杂度不对 然后由于每一行互不影响于是可以单行同 ...

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

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

  6. P2216 理想的正方形 单调队列 (二维)

    题目链接:https://www.luogu.org/problem/P2216 题意:求给定n*m的矩形中所有k*k的正方形块中最大值最小值之差(极差)最小 哇,大神的思路真的很帅 单调队列对每一行 ...

  7. bzoj1047/luogu2216 理想的正方形 (单调队列)

    开b组单调队列,分别维护此时某一列中的最大/最小值 然后我每次把它们的头取出来,塞到维护行的单调队列里,就是n*n的最大/最小值 1 #include<bits/stdc++.h> 2 # ...

  8. AcWing1091.理想的正方形(单调队列DP)

    题目传送门 有一个 a×b 的整数组成的矩阵,现请你从中找出一个 n×n 的正方形区域,使得该区域所有数中的最大值和最小值的差最小. 输入格式 第一行为三个整数,分别表示 a,b,n 的值: 第二行至 ...

  9. [HAOI2007] 理想的正方形

    洛谷题目链接:[HAOI2007]理想的正方形 题目描述 有一个ab的整数组成的矩阵,现请你从中找出一个nn的正方形区域,使得该区域所有数中的最大值和最小值的差最小. 输入输出格式 输入格式: 第一行 ...

最新文章

  1. C++11库中 steady_clock , system_clock和high_resolution_clock的区别
  2. 信息学奥赛C++语言:打擂台
  3. 使用Acronis Disk Director Suite调整分区大小
  4. 三层架构学习的困难_TCP/IP协议栈-之-三层交换技术
  5. JavaScript异步编程的四种方法(转)
  6. pycharm 改成中文亲测好用
  7. Java全套视频教程
  8. HTML5 怎么自定义字体
  9. 如何录屏制作动态图片,并在markdown中显示
  10. Tomcat 安装Namecheap SSL证书教程
  11. 恢复Surface Pro 高级电源设置里各类配置项提高外接电源模式下的性能(外接电源莫名很卡,拔掉电源又正常,实则被降频)
  12. Python基础操作(2)
  13. 字符串前面加f是什么意思?
  14. html 苹果 地图,为什么苹果手机自带的地图是高德而不是谷歌?
  15. SAR 三点回波模拟 正侧视RD算法(经典好用)
  16. datadog的数据流转
  17. 2018年我国互联网网络安全态势综述
  18. Android 实现ListView的展开式动画ExpandAnimation
  19. 创世茶小Y系列—茶元后·龙门飞瀑来袭
  20. python可以干什么

热门文章

  1. 程序员数学基础【四、取模应用-判断奇偶数、判断素数、求两个数的最大公约数、水仙花数】(Python版本)
  2. 如何将加密PDF转换成Word文档
  3. letecode [160] - Intersection of Two Linked Lists
  4. 《linux就该这么学》第七节课:文件的各种权限以及linux分区命名规则
  5. android EventBus的简单使用
  6. 虚幻4 ue4 学习笔记pwan篇 1.4 pawn结合UPawnMovementComponent类 移动组件实现 移动球体添加物理碰撞...
  7. [poj] 2749 building roads
  8. Linux常用命令和常见问题解决------第一章
  9. 15.RDD 创建内幕解析
  10. .net利用程序集的GUID解决程序只能运行一次的问题