AcWing1091.理想的正方形(单调队列DP)
题目传送门
有一个 a×b 的整数组成的矩阵,现请你从中找出一个 n×n 的正方形区域,使得该区域所有数中的最大值和最小值的差最小。
输入格式
第一行为三个整数,分别表示 a,b,n 的值;
第二行至第 a+1 行每行为 b 个非负整数,表示矩阵中相应位置上的数。
输出格式
输出仅一个整数,为 a×b 矩阵中所有“n×n 正方形区域中的最大整数和最小整数的差值”的最小值。
数据范围
2≤a,b≤1000
n≤a,n≤b,n≤100
矩阵中的所有数都不超过 109。
输入样例:
5 4 2
1 2 5 6
0 17 16 0
16 17 2 1
2 10 2 1
1 2 2 2
输出样例:
1
题解:
1.对于每一行,我们先求出以 i 为右端点的, 且长度在n的范围内的最大值和最小值, 分别存到row_max[i] 和
row_min[i] 中去
2.对于每一列, 我们遍历已经得到的 row_max 数组和 row_min 数组, 分别得到在这一列上以j为右下端点,且长
度在n的范围内的最大值和最小值分别存储到 b[j] 和 c[j] 中去,这样我们就得到了以 (i, j) 为右下顶点且行和列的长度为 n 的矩阵的最大值和最小值
3.遍历所有的列的同时,求出max(b[j] - c[j]) 就是最终的答案
#include<iostream>
using namespace std;
const int N = 1010;
int w[N][N], row_min[N][N], row_max[N][N];
int st[N];
int n, m, k;
void get_min(int a[], int b[], int n) //获取最小值,
{int l = 0, r = -1;for(int i = 1; i <= n; i++){while(l <= r && i - st[l] >= k)l++;while(l <= r && a[i] <= a[st[r]])r--;st[++r] = i;b[i] = a[st[l]];}
}
void get_max(int a[], int b[], int n) //获取最大值
{int l = 0, r = -1;for(int i = 1; i <= n; i++){while(l <= r && i - st[l] >= k)l++;while(l <= r && a[i] >= a[st[r]])r--;st[++r] = i;b[i] = a[st[l]];}
}
int main()
{scanf("%d%d%d", &n, &m, &k);for(int i = 1; i <= n; i++)for(int j = 1; j <= m; j++)scanf("%d", &w[i][j]);for(int i = 1; i <= n; i++){get_min(w[i], row_min[i], m);get_max(w[i], row_max[i], m);}int ans = 1e9;int a[N], b[N], c[N];for(int i = k; i <= m; i++){for(int j = 1; j <= n; j++) a[j] = row_max[j][i];get_max(a, b, n);for(int j = 1; j <= n; j++) a[j] = row_min[j][i];get_min(a, c, n);for(int j = k; j <= n; j++) ans = min(ans, b[j] - c[j]);}cout << ans << endl;return 0;
}
AcWing1091.理想的正方形(单调队列DP)相关推荐
- P2216 理想的正方形 单调队列 (二维)
题目链接:https://www.luogu.org/problem/P2216 题意:求给定n*m的矩形中所有k*k的正方形块中最大值最小值之差(极差)最小 哇,大神的思路真的很帅 单调队列对每一行 ...
- BZOJ 1047 理想的正方形(单调队列)
刚开始用二维RMQ直接给超内存了... 用单调队列可以做到O(n^2)的复杂度.具体是先把每行用单调队列处理一下.再把处理后的用列单调队列处理下. # include <cstdio> # ...
- [HAOI2007] 理想的正方形 (单调队列)
题目链接 Solution MD,经过这道题,算是掌握单调队列了... 可以先预处理出点 \((i,j)\) 往上 \(n\) 的最大值和最小值. 然后再横着做一遍单调队列即可. Code #incl ...
- BZOJ 1047: [HAOI2007]理想的正方形 单调队列瞎搞
题意很简明吧? 枚举的矩形下边界和右端点即右下角,来确定矩形位置: 每一个纵列开一个单调队列,记录从 i-n+1 行到 i 行每列的最大值和最小值,矩形下边界向下推移的时候维护一下: 然后在记录的每一 ...
- bzoj1047/luogu2216 理想的正方形 (单调队列)
开b组单调队列,分别维护此时某一列中的最大/最小值 然后我每次把它们的头取出来,塞到维护行的单调队列里,就是n*n的最大/最小值 1 #include<bits/stdc++.h> 2 # ...
- bzoj1047 [HAOI2007]理想的正方形 单调队列
这种在矩形里面找矩形有固定的套路,不是容斥就是左右上下延伸,这个题就是向左向右延伸.. 然后手玩优化发现邻位转移比暴力要好一些,可以用splay统计,但复杂度不对 然后由于每一行互不影响于是可以单行同 ...
- bzoj1791,P4381-[IOI2008]Island【基环树,树形dp,单调队列dp,树的直径】
正题 评测记录:https://www.luogu.org/recordnew/lists?uid=52918&pid=P4381 题目大意 有n个岛,n条无向边(保证每个岛都有边连到).走过 ...
- P3580 [POI2014]ZAL-Freight(单调队列dp)
P3580 [POI2014]ZAL-Freight(单调队列dp) 考虑两辆车怎么样是最优的. t1,t2,St_1,t_2,St1,t2,S t1+St_1+St1+S 第一辆车:[t1,t ...
- 刷题总结——烽火传递(单调队列+dp)
题目: 题目描述 烽火台又称烽燧,是重要的防御设施,一般建在险要处或交通要道上.一旦有敌情发生,白天燃烧柴草,通过浓烟表达信息:夜晚燃烧干柴,以火光传递军情.在某两座城市之间有 n 个烽火台,每个烽火 ...
最新文章
- vs2010 vc nmake编译openssl-0.9.8e
- 【深度学习】用Pytorch给你的母校做一个样式迁移吧!
- 从服务器恢复系统,服务器恢复系统
- 华为鸿蒙系统支持什么手机_什么样的手机可以刷鸿蒙系统?看看你的手机支持吗?...
- ic 卡获取帐号apdu指令_《全球行动》携手京东校园送福利 1000元京东卡等你拿
- Python风格总结: OS 文件/目录方法
- ORCLE conn连接报错
- 教育统计与测量【1】
- 计算机制图系统的组成,lesson02-计算机机地图制图系统的组成.ppt
- SAI颈部正面的画法
- 蓝牙HID——将android设备变成蓝牙鼠标/触控板(BluetoothHidDevice)
- idea git暂存操作
- WebLogic 10.3.1 下载地址
- 什么是PWM 和PFM?
- Matlab中创建和使用表
- python计算频率_如何计算给定波的频率和时间
- mac PhotoshopCS6 破解安装
- pyqt5制作指示灯
- Java ME引路蜂地图开发示例:第一个地图应用
- python3GUI--200行代码写一个上课点名程序(附源码)