【二维单调队列】BZOJ1047-[HAOI2007]理想的正方形
【题目大意】
有一个a*b的整数组成的矩阵,现请你从中找出一个n*n的正方形区域,使得该区域所有数中的最大值和最小值的差最小。
【思路】
裸的二维单调队列。二维单调队列的思路其实很简单:
(1)对于每一行维护两个宽度为n的滑动窗口记录单行中的min和max,和POJ2823一个道理。此时相当于把n个格子浓缩到了一个格子当中。
(2)维护n*n大小的二维滑动窗口中的min和max。由于有了第一步操作,只要考虑每一个n*n的矩形右上角到右下角的最值即可。相当于对于每一列,维护两个宽度为n的滑动窗口。此时循环要行和列里外颠倒,而列只要从第n列开始维护即可(我一开始就错在了这两个地方)
- #include<iostream>
- #include<cstdio>
- #include<cstring>
- #include<algorithm>
- #define INF 0x7fffffff
- struct node
- {
- int data,pos;
- };
- using namespace std;
- const int MAXN=+;
- int a,b,n;
- int num[MAXN][MAXN];
- int rmin[MAXN][MAXN],rmax[MAXN][MAXN],smin[MAXN][MAXN],smax[MAXN][MAXN];
- void init()
- {
- scanf("%d%d%d",&a,&b,&n);
- for (int i=;i<a;i++)
- for (int j=;j<b;j++) scanf("%d",&num[i][j]);
- }
- void humdrum_queue()
- {
- /*对于每一行,用单调队列维护[x-n+1,x]的最小值和最大值*/
- for (int i=;i<a;i++)
- {
- int minhead=,mintail=,maxhead=,maxtail=;
- node qmin[MAXN],qmax[MAXN];
- for (int j=;j<b;j++)
- {
- int nown=num[i][j];
- /*维护最小值*/
- while (minhead<mintail && qmin[mintail-].data>nown) mintail--;
- qmin[mintail++]=(node){nown,j};
- while (minhead<mintail && qmin[minhead].pos<=j-n) minhead++;
- rmin[i][j]=qmin[minhead].data;
- /*维护最大值*/
- while (maxhead<maxtail && qmax[maxtail-].data<nown) maxtail--;
- qmax[maxtail++]=(node){nown,j};
- while (maxhead<maxtail && qmax[maxhead].pos<=j-n) maxhead++;
- rmax[i][j]=qmax[maxhead].data;
- }
- }
- /*对于以[i,j]为右下角的n*n矩形,用单调队列维护它的最小值和最大值
- 这步操作可以用单调队列维护每一列,相当于维护该矩形右上角到右下角对应点的rmin与rmax值*/
- /*|ATTENTION|要注意的是这里i和j要颠倒过来,所以内外循环以及队列中的pos均要颠倒!*/
- for (int j=n-;j<b;j++)
- {
- int minhead=,mintail=,maxhead=,maxtail=;
- node qmin[MAXN],qmax[MAXN];
- for (int i=;i<a;i++)
- {
- int nowmin=rmin[i][j],nowmax=rmax[i][j];
- /*维护最小值*/
- while (minhead<mintail && qmin[mintail-].data>nowmin) mintail--;
- qmin[mintail++]=(node){nowmin,i};
- while (minhead<mintail && qmin[minhead].pos<=i-n) minhead++;
- smin[i][j]=qmin[minhead].data;
- /*维护最大值*/
- while (maxhead<maxtail && qmax[maxtail-].data<nowmax) maxtail--;
- qmax[maxtail++]=(node){nowmax,i};
- while (maxhead<maxtail && qmax[maxhead].pos<=i-n) maxhead++;
- smax[i][j]=qmax[maxhead].data;
- }
- }
- }
- void getans()
- {
- int ans=INF;
- for (int i=n-;i<a;i++)
- for (int j=n-;j<b;j++)
- if (smax[i][j]-smin[i][j]<ans) ans=smax[i][j]-smin[i][j];
- cout<<ans<<endl;
- }
- int main()
- {
- init();
- humdrum_queue();
- getans();
- return ;
- }
【二维单调队列】BZOJ1047-[HAOI2007]理想的正方形的更多相关文章
- bzoj1047-理想的正方形(二维单调队列)
题意: 给一个矩阵,给出行列和每个数,再给出一个N,求出所有N*N的子矩阵中最大值最小值之差的最小值解析: 暴力枚举肯定不行,这题可以用二维单调队列做,把同一行的连续N个点缩成一个点保存最大最小值预处 ...
- BZOJ1047: [HAOI2007]理想的正方形 [单调队列]
1047: [HAOI2007]理想的正方形 Time Limit: 10 Sec Memory Limit: 162 MBSubmit: 2857 Solved: 1560[Submit][St ...
- bzoj千题计划215:bzoj1047: [HAOI2007]理想的正方形
http://www.lydsy.com/JudgeOnline/problem.php?id=1047 先用单调队列求出每横着n个最大值 再在里面用单调队列求出每竖着n个的最大值 这样一个位置就代表 ...
- [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 ...
- [bzoj1047][HAOI2007]理想的正方形_动态规划_单调队列
理想的正方形 bzoj-1047 HAOI-2007 题目大意:有一个a*b的整数组成的矩阵,现请你从中找出一个n*n的正方形区域,使得该区域所有数中的最大值和最小值的差最小. 注释:$2\le a, ...
- BZOJ1047[HAOI2007]理想的正方形——二维ST表
题目描述 有一个a*b的整数组成的矩阵,现请你从中找出一个n*n的正方形区域,使得该区域所有数中的最大值和最小值的差最小. 输入 第一行为3个整数,分别表示a,b,n的值第二行至第a+1行每行为b个非 ...
- 【单调队列】bzoj1047 [HAOI2007]理想的正方形
先把整个矩阵处理成b[n][m-K+1].c[n][m-K+1]大小的两个矩阵,分别存储每行每K个数中的最大.最小值,然后再通过b.c处理出d.e分别表示K*K大小的子矩阵中的最大.最小值即可.单调队 ...
随机推荐
- angular js自定义service的简单示例
<!DOCTYPE html><html lang="en"><head> <meta charset="UTF-8" ...
- TCP ------ TCP创建服务器中出现的套接字
在服务器端,socket()返回的套接字用于监听(listen)和接受(accept)客户端的连接请求.这个套接字不能用于与客户端之间发送和接收数据. accept()接受一个客户端的连接请求,并返回 ...
- Install the Active Directory Administration Tools on Windows Server
安装 Active Directory 管理工具 To manage your directory from an EC2 Windows instance, you need to install ...
- JS表单验证优化
var validate = (function(){ var messages = { isEmail : '输入正确格式邮箱', isPhoneNum : '输入正确手机号' }; var val ...
- lesson 4 再谈继承多态,抽象类和接口
再谈多态,抽象类和接口 上一次博客已经概念性的概述了继承多态,抽象类和接口,这次来具体的谈一谈他们之间的联系和需要注意的地方. 一.继承和多态:Inheritance (继承) & Polym ...
- Go 实现 soundex 算法
[转]http://www.syyong.com/Go/Go-implements-the-soundex-algorithm.html SOUNDEX 返回由四个字符组成的代码 (SOUNDEX) ...
- [bzoj3524==bzoj2223][Poi2014]Couriers/[Coci 2009]PATULJCI——主席树+权值线段树
题目大意 给定一个大小为n,每个数的大小均在[1,c]之间的数列,你需要回答m个询问,其中第i个询问形如\((l_i, r_i)\),你需要回答是否存在一个数使得它在区间\([l_i,r_i]\)中出 ...
- poj 2406 Power Strings(kmp循环节)
题目链接:http://poj.org/problem?id=2406 题目大意:如果n%(n-next[n])==0,则存在重复连续子串,长度为n-next[n]. 例如: a b ...
- 时间模块(time/date)
在Python中,常用的表示方式的时间有:时间戳,字符串时间,元组时间(既年,月,日,时,分,秒,周几,一年中的第几天,时区) time模块: time.timezone: 获取当前标准时 ...
- DDD——让天下没有难调的程序
https://www.linuxidc.com/Linux/2016-11/137343.htm DDD全称Data Display Debugger,当我第一次见到它时,它的界面着实让我吃了一惊, ...