BZOJ 1047 二维单调队列
题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=1047
题意:见中文题面
思路:该题是求二维的子矩阵的最大值与最小值的差值尽量小。所以可以考虑求出每个子矩阵的最大值和最小值。考虑一维求子段的最小值/最大值的思路。滑动窗口+单调队列。 转换成二维。设minNum[i][j]表示右下角为(i,j)的子矩阵的最小值。先对矩阵每一行用一维的做法求出每一行的子段的最小值,然后同样的方法求列的最值。注意在求列的子段最小值时比较的元素不是原矩阵的元素而是用行求的结果来比较。 具体看代码吧。
#define _CRT_SECURE_NO_DEPRECATE
#include<stdio.h>
#include<string.h>
#include<cstring>
#include<algorithm>
#include<queue>
#include<math.h>
#include<time.h>
#include<vector>
#include<iostream>
#include<string>
using namespace std;
typedef long long int LL;
const int MAXN = + ;
const int INF = 0x3f3f3f3f;
int n, m, k, num[MAXN][MAXN], minNum[MAXN][MAXN], maxNum[MAXN][MAXN];
void solve(int type, int seg[][MAXN]){
deque<pair<int, int> > deq;
for (int i = ; i <= n; i++){ //求行子段的最值。
deq.clear();
for (int j = ; j <= m; j++){
while (!deq.empty() && j - deq.front().second >= k){ deq.pop_front(); }
if (type){
while (!deq.empty() && deq.back().first < num[i][j]){ deq.pop_back(); }
}
else{
while (!deq.empty() && deq.back().first > num[i][j]){ deq.pop_back(); }
}
deq.push_back(make_pair(num[i][j], j));
seg[i][j] = deq.front().first;
}
}
for (int j = ; j <= m; j++){ //求列的最值
deq.clear();
for (int i = ; i <= n; i++){
while (!deq.empty() && i - deq.front().second >= k){ deq.pop_front(); }
if (type){
while (!deq.empty() && deq.back().first < seg[i][j]){ deq.pop_back(); }
}
else{
while (!deq.empty() && deq.back().first > seg[i][j]){ deq.pop_back(); }
}
deq.push_back(make_pair(seg[i][j], i));
seg[i][j] = deq.front().first;
}
}
}
int main(){
//#ifdef kirito
// freopen("in.txt", "r", stdin);
// freopen("out.txt", "w", stdout);
//#endif
// int start = clock();
while (~scanf("%d%d%d", &n, &m, &k)){
for (int i = ; i <= n; i++){
for (int j = ; j <= m; j++){
scanf("%d", &num[i][j]);
}
}
int ans = INF;
solve(, minNum); solve(, maxNum);
////Debug
//printf("minNum Segment:\n");
//for (int i = 1; i <= n; i++){
// for (int j = 1; j <= m; j++){
// printf("%d ", minNum[i][j]);
// }
// printf("\n");
//}
//printf("maxNum Segment:\n");
//for (int i = 1; i <= n; i++){
// for (int j = 1; j <= m; j++){
// printf("%d ", maxNum[i][j]);
// }
// printf("\n");
//}
for (int i = k; i <= n; i++){
for (int j = k; j <= m; j++){
ans = min(ans, maxNum[i][j] - minNum[i][j]);
}
}
printf("%d\n", ans);
}
//#ifdef LOCAL_TIME
// cout << "[Finished in " << clock() - start << " ms]" << endl;
//#endif
return ;
}
BZOJ 1047 二维单调队列的更多相关文章
- bzoj1047-理想的正方形(二维单调队列)
题意: 给一个矩阵,给出行列和每个数,再给出一个N,求出所有N*N的子矩阵中最大值最小值之差的最小值解析: 暴力枚举肯定不行,这题可以用二维单调队列做,把同一行的连续N个点缩成一个点保存最大最小值预处 ...
- 【二维单调队列】BZOJ1047-[HAOI2007]理想的正方形
[题目大意] 有一个a*b的整数组成的矩阵,现请你从中找出一个n*n的正方形区域,使得该区域所有数中的最大值和最小值的差最小. [思路] 裸的二维单调队列.二维单调队列的思路其实很简单: (1)对于每 ...
- [BZOJ1047][HAOI2007]理想的正方形 二维单调队列
题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=1047 我们对每矩阵的一列维护一个大小为$n$的单调队列,队中元素为矩阵中元素.然后扫描每一 ...
- bzoj1047 [HAOI2007]理想的正方形——二维单调队列
题目:https://www.lydsy.com/JudgeOnline/problem.php?id=1047 就是先对行做一遍单调队列,再对那个结果按列做一遍单调队列即可. 代码如下: #incl ...
- [luoguP2216] [HAOI2007]理想的正方形(二维单调队列)
传送门 1.先弄个单调队列求出每一行的区间为n的最大值最小值. 2.然后再搞个单调队列求1所求出的结果的区间为n的最大值最小值 3.最后扫一遍就行 懒得画图,自己体会吧. ——代码 #include ...
- bzoj 2216: Lightning Conductor 单调队列优化dp
题目大意 已知一个长度为\(n\)的序列\(a_1,a_2,...,a_n\)对于每个\(1\leq i\leq n\),找到最小的非负整数\(p\)满足: 对于任意的\(j\), \(a_j \le ...
- BZOJ 1855 股票交易(单调队列优化DP)
题目链接:http://61.187.179.132/JudgeOnline/problem.php?id=1855 题意:最近lxhgww又迷上了投资股票, 通过一段时间的观察和学习,他总结出了股票 ...
- BZOJ 2424 订货(贪心+单调队列)
怎么题解都是用费用流做的啊...用单调队列多优美啊. 题意:某公司估计市场在第i个月对某产品的需求量为Ui,已知在第i月该产品的订货单价为di,上个月月底未销完的单位产品要付存贮费用m,假定第一月月初 ...
- BZOJ 1012 线段树||单调队列
非常裸的线段树 || 单调队列: 假设一个节点在队列中既没有时间优势(早点入队)也没有值优势(值更大),那么显然不管在如何的情况下都不会被选为最大值. 既然它仅仅在末尾选.那么自然能够满足以上的条件 ...
随机推荐
- Linux 从零开始
从Windows进入linux有太多不适应,对代码一无所知,接触Linux,从简单的开始垒砌. 加油最好的自己!
- django(一)
Django 自称是"最适合开发有限期的完美WEB框架".本文参考<Django web开发指南>,快速搭建一个blog 出来,在中间涉及诸多知识点,这里不会详细说明, ...
- JS打开新页面跳转
有时候使用js进行页面跳转,想使用 a 标签中 target="_blank" 形式,跳转打开一个新的页面. 可以使用以下脚本,创建一个 a标签,然后模拟点击操作. 代码如下: ...
- Linux kernel4.4.12 添加make menuconfig 可选项
Linux kernel 源码添加可选项 闲来无事,顺便记录一篇在Linux kernel make menuconfig 内添加一个可选项. 说不定将来就要用到这个东西呢. linux kernel ...
- markdown编辑器sublime text3
安装包管理Package Control ctrl+`或者点击查看-->显示面板,复制下面的代码到面板里. import urllib.request,os; pf = 'Package Con ...
- linux查看安装文件
rpm -qa jdk 查看名字包含"jdk"的已安装的文件 which java 查看java命令的所在目录 rpm -qf `which java` 查看java命令所对应的安 ...
- Redis持久化
Redis持久化 快照(默认) 将内存中的数据以快照的方式写入到二进制文件中,默认文件名是dump.rdb. 配置自动化做快照持久化(如redis在n秒内如果超过m个key被修改就自动做快照) sav ...
- How to see the "real" available resources ?
Hi, Hope this will help you : nova hypervisor-stats It will return the statistics of the Hypervisor ...
- Java中的堆栈区别
在函数中定义的一些基本类型的变量和对象的引用变量都在函数的栈内存中分配. 当在一段代码块定义一个变量时,Java就在栈中为这个变量分配内存空间,当超过变量的作用域后,Java会自动释放掉为该变量所分配 ...
- 2016ACM青岛区域赛题解
A.Relic Discovery_hdu5982 Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/65536 K (Jav ...