bzoj1047 单调队列
来源:互联网 发布:nc.windows.app.23787 编辑:程序博客网 时间:2024/06/14 00:58
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
还在为学不会单调队列而苦恼么?
还在看一篇又一篇写的很诡异的博客么?
我们已经为你准备了一大堆习题来教你单调队列,我们保证你绝对做到吐
单调队列单调队列顾名思义队列里面的元素是有单调性的要么递增要么递减
我们考虑,一个靠后的点虽然可能在数值上不占优势但是它可以更新的更远,但是如果他在数值上也占优势的话那么前面的点不就很没用了么,那么就让他们全部出队。当队列滑动的过程中要把不合题意的点出队。这就是单调队列优化dp
那么这个题也就比较明确了。
那么此题其实是一个非常裸的二维单调队列。
用max【i】【j】表示以(i,j)为右下角的最大值
那么我们先求出每一行的情况然后求出前i行的情况
#include<cstdio>#include<cstring>#include<utility>#include<algorithm>#include<iostream>#include<queue>#include<stack>#include<cmath>#include<cstdlib>#include<ctime>using namespace std;inline int read(){ char ch='*'; int f=1; while(!isdigit(ch=getchar())) if(ch=='-') f=-1; int num=ch-'0'; while(isdigit(ch=getchar())) num=num*10+ch-'0'; return num*f;}const int N=1005;int mp[N][N],h[N],t[N],Q[N],q[N][N];int mx[N][N],mn[N][N];int s,e,a,b,n;void getmax(){ for(register int i=1;i<=b;++i) h[i]=1,t[i]=0; for(register int i=1;i<=a;++i){ for(register int j=1;j<=b;++j) { while(h[j]<=t[j]&&i-q[j][h[j]]>=n) ++h[j]; while(h[j]<=t[j]&&mp[q[j][t[j]]][j]<=mp[i][j]) --t[j]; q[j][++t[j]]=i; } e=0,s=1; for(register int j=1;j<=b;j++){ while(s<=e&&j-Q[s]>=n) ++s; while(s<=e&&mp[q[Q[e]][h[Q[e]]]][Q[e]]<=mp[q[j][h[j]]][j]) e--; Q[++e]=j; mx[i][j]=mp[q[Q[s]][h[Q[s]]]][Q[s]]; } } return ;}void getmin(){ for(register int i=1;i<=b;++i) h[i]=1,t[i]=0; for(register int i=1;i<=a;++i){ for(register int j=1;j<=b;++j) { while(h[j]<=t[j]&&i-q[j][h[j]]>=n) ++h[j]; while(h[j]<=t[j]&&mp[q[j][t[j]]][j]>=mp[i][j]) --t[j]; q[j][++t[j]]=i; } e=0,s=1; for(register int j=1;j<=b;j++){ while(s<=e&&j-Q[s]>=n) ++s; while(s<=e&&mp[q[Q[e]][h[Q[e]]]][Q[e]]>=mp[q[j][h[j]]][j]) e--; Q[++e]=j; mn[i][j]=mp[q[Q[s]][h[Q[s]]]][Q[s]]; } } return ;}int main(){ a=read();b=read();n=read(); for(register int i=1;i<=a;i++) for(register int j=1;j<=b;j++) mp[i][j]=read(); getmax(); getmin(); int ans=0x7fffffff; for(int i=n;i<=a;i++) for(register int j=n;j<=b;j++) ans=min(ans,mx[i][j]-mn[i][j]); printf("%d\n",ans); return 0;}
阅读全文
0 0
- bzoj1047 单调队列
- 【bzoj1047】【单调队列】【HAOI2007】理想的正方形
- 【bzoj1047】【HAOI2007】【理想的正方形】【单调队列】
- bzoj1047(单调队列,矩阵中)
- BZOJ1047: [HAOI2007]理想的正方形 单调队列
- bzoj1047[HAOI2007]理想的正方形 单调队列
- bzoj1047 [HAOI2007]理想的正方形 单调队列
- [BZOJ1047]HAOI2007理想的正方形|单调队列|DP
- [BZOJ1047][HAOI2007]理想的正方形(单调队列)
- 【单调队列】BZOJ1047(HAOI2007)[理想的正方形]题解
- [bzoj1047][HAOI2007]理想的正方形(单调队列)
- bzoj1047 [HAOI2007]理想的正方形(单调队列)
- BZOJ1047
- BZOJ1047
- bzoj1047
- BZOJ1047
- 【BZOJ1047】理想的正方形 堆套堆 优先队列
- 单调栈 单调队列
- Visual Studio扩展开发之菜单设置--拒绝反复输入样板代码,编写IDE插件,提升编码效率
- iphone恢复删除的文件-不要钱!
- webService理解
- Oracle 删除重复数据只留一条 查询及删除重复记录的SQL语句 1、查找表中多余的重复记录,重复记录是根据单个字段(Id)来判断 select * from 表 wher
- Linux system 存储设备的管理
- bzoj1047 单调队列
- 将oracle的dmp导入到不同表空间 oracle的dmp文件导入到不同表空间 oracle将dmp文件导入到不同的表空间方法: 1、exp USER/PASSOWRD@SID file=c:\t
- SeetaFaceEngine/FaceAlignment/
- 小白程序员的第二天
- 静态导入
- html5新增属性
- iOS 11更新后以及iPhone X推出后工程中遇到的问题及适配
- NOIP赛前常用模板代码总结
- html基本样式