【HAOI2007】理想的正方形
【问题描述】
有一个a*b的整数组成的矩阵,现请你从中找出一个n*n的正方形区域,使得该区域所有数中的最大值和最小值的差最小。
【输入】
第一行为3个整数,分别表示a,b,n的值
第二行至第a+1行每行为b个非负整数,表示矩阵中相应位置上的数。每行相邻两数之间用一空格分隔。
【输出】
仅一个整数,为a*b矩阵中所有“n*n正方形区域中的最大整数和最小整数的差值”的最小值。
【分析】
单调队列,先处理横行,再处理竖行。
#include <cstdlib>
#include <iostream>
#include <cmath>
#include <cstdio>
#include <cstring>
const int MAX=;
const int INF=0x7fffffff;
using namespace std;
//注意Max与Min(i,j)代表第i行从
int data[MAX][MAX],Max[MAX][MAX],Min[MAX][MAX];
int a,b,n,ans=INF; void init();//输入数据
void solve();
void prepare(int hang);
void work(int lie); int main()
{
//文件操作
freopen("square.in","r",stdin);
freopen("square.out","w",stdout);
init();//输入数据
solve();//求解
return ;
}
void init()
{
scanf("%d%d%d",&a,&b,&n);
for (int i=;i<=a;i++)
for (int j=;j<=b;j++)
scanf("%d",&data[i][j]);
}
void solve()
{
//计算出每行各个元素的最大值与最小值
for (int i=;i<=a;i++) prepare(i);//横推行
// printf("\n");
for (int i=n;i<=b;i++) work(i);//纵推列
printf("%d\n",ans);
}
void prepare(int hang)
{
int Q_MAX[MAX],front_MAX=,rear_MAX=;
int Q_MIN[MAX],front_MIN=,rear_MIN=;
for (int i=;i<=n;i++)//预处理
{
while (front_MAX<rear_MAX && data[hang][Q_MAX[rear_MAX]]<data[hang][i]) rear_MAX--;
Q_MAX[++rear_MAX]=i;
while (front_MIN<rear_MIN && data[hang][Q_MIN[rear_MIN]]>data[hang][i]) rear_MIN--;
Q_MIN[++rear_MIN]=i;
}
//开始计算,千万要注意边界问题
for (int i=n;i<=b;i++)
{
//先计算MAX与MIN值
while (front_MAX<rear_MAX && Q_MAX[front_MAX+]<(i-n+)) front_MAX++;
Max[hang][i]=data[hang][Q_MAX[front_MAX+]];
while (front_MIN<rear_MIN && Q_MIN[front_MIN+]<(i-n+)) front_MIN++;
Min[hang][i]=data[hang][Q_MIN[front_MIN+]];
//再考虑加入队列
while (front_MAX<rear_MAX && data[hang][Q_MAX[rear_MAX]]<data[hang][i+]) rear_MAX--;
Q_MAX[++rear_MAX]=i+;
while (front_MIN<rear_MIN && data[hang][Q_MIN[rear_MIN]]>data[hang][i+]) rear_MIN--;
Q_MIN[++rear_MIN]=i+;
}
//打印
//for (int i=n;i<=b;i++) printf("(%d %d) ",Max[hang][i],Min[hang][i]);
// printf("\n");
}
void work(int lie)
{
//printf("%d:",lie);
int Q_MAX[MAX],front_MAX=,rear_MAX=;
int Q_MIN[MAX],front_MIN=,rear_MIN=;
for (int i=;i<=n;i++)//预处理,注意这里换成行了
{
while (front_MAX<rear_MAX && Max[Q_MAX[rear_MAX-]][lie]<Max[i][lie]) rear_MAX--;
Q_MAX[rear_MAX++]=i;
while (front_MIN<rear_MIN && Min[Q_MIN[rear_MIN-]][lie]>Min[i][lie]) rear_MIN--;
Q_MIN[rear_MIN++]=i;
}
//开始计算,千万要注意边界问题
for (int i=n;i<=a;i++)
{
while (front_MAX<rear_MAX && Q_MAX[front_MAX]<(i-n+)) front_MAX++;
while (front_MIN<rear_MIN && Q_MIN[front_MIN]<(i-n+)) front_MIN++;
ans=min(ans,Max[Q_MAX[front_MAX]][lie]-Min[Q_MIN[front_MIN]][lie]); //printf("(%d %d) ",Q_MAX[front_MAX],Q_MIN[front_MIN]);
//再考虑加入队列
while (front_MAX<rear_MAX && Max[Q_MAX[rear_MAX-]][lie]<Max[i+][lie]) rear_MAX--;
Q_MAX[rear_MAX++]=i+;
while (front_MIN<rear_MIN && Min[Q_MIN[rear_MIN-]][lie]>Min[i+][lie]) rear_MIN--;
Q_MIN[rear_MIN++]=i+;
}
//printf("\n");
}
【HAOI2007】理想的正方形的更多相关文章
- BZOJ1047: [HAOI2007]理想的正方形 [单调队列]
1047: [HAOI2007]理想的正方形 Time Limit: 10 Sec Memory Limit: 162 MBSubmit: 2857 Solved: 1560[Submit][St ...
- HAOI2007 理想的正方形
1047: [HAOI2007]理想的正方形 Time Limit: 10 Sec Memory Limit: 162 MBSubmit: 1402 Solved: 738[Submit][Sta ...
- RAM——[HAOI2007]理想的正方形
题目:[HAOI2007]理想的正方形 描述: [问题描述] 有一个a*b的整数组成的矩阵,现请你从中找出一个n*n的正方形区域,使得该区域所有数中的最大值和最小值的差最小. [输入]: 第一行为3个 ...
- bzoj 1047 : [HAOI2007]理想的正方形 单调队列dp
题目链接 1047: [HAOI2007]理想的正方形 Time Limit: 10 Sec Memory Limit: 162 MBSubmit: 2369 Solved: 1266[Submi ...
- BZOJ 1047: [HAOI2007]理想的正方形( 单调队列 )
单调队列..先对每一行扫一次维护以每个点(x, y)为结尾的长度为n的最大最小值.然后再对每一列扫一次, 在之前的基础上维护(x, y)为结尾的长度为n的最大最小值. 时间复杂度O(ab) (话说还是 ...
- 【BZOJ1047】[HAOI2007]理想的正方形(单调队列,动态规划)
[BZOJ1047][HAOI2007]理想的正方形(单调队列,动态规划) 题面 BZOJ 洛谷 题解 直接一个单调队列维护一下没给点和它前面的\(n\)个位置的最大值,再用一次单调队列维护连续\(n ...
- bzoj千题计划215:bzoj1047: [HAOI2007]理想的正方形
http://www.lydsy.com/JudgeOnline/problem.php?id=1047 先用单调队列求出每横着n个最大值 再在里面用单调队列求出每竖着n个的最大值 这样一个位置就代表 ...
- 【BZOJ1047】[HAOI2007]理想的正方形
[BZOJ1047][HAOI2007]理想的正方形 题面 bzoj 洛谷 题解 二维\(st\)表,代码是以前的 #include<iostream> #include<cstdi ...
- 【BZOJ1047】[HAOI2007]理想的正方形 (倍增ST表)
[HAOI2007]理想的正方形 题目描述 有一个\(a*b\)的整数组成的矩阵,现请你从中找出一个\(n*n\)的正方形区域,使得该区域所有数中的最大值和最小值的差最小. 输入输出格式 输入格式: ...
- AC日记——[HAOI2007]理想的正方形 P2216
[HAOI2007] 理想的正方形 思路: 正解多个单调队列: 但是我用树套树水了过去: 来,上代码: #include <cstdio> #include <cstring> ...
随机推荐
- 用 SQL 脚本读取Excel 中的sheet数量及名称
-- Get table (worksheet) or column (field) listings from an excel spreadsheet -- 设置变量 declare @linke ...
- 更改Visual Studio 2010/2012/2008的主题设置
一.更改主题: 主题网站:http://studiostyl.es/ Visual Studio 2010发布也已经有一段时间了,不过安装后默认的白底的主题长时间看代码可能会感觉眼睛酸痛,况且时间长了 ...
- 网络流(最小费用最大流):POJ 2135 Farm Tour
Farm Tour Time Limit: 1000ms Memory Limit: 65536KB This problem will be judged on PKU. Original ID: ...
- 【动态规划】HDU 5781 ATM Mechine
题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=5781 题目大意: 一个人有[0,K]内随机的钱,每次可以随意取,但是不知道什么时候取完,取钱超过剩余 ...
- 不允许从数据类型 nvarchar 到 varbinary 的隐式转换
一:错误截图 二:解决 数据库里面的数据类型错了,应该是varchar,而我选了varbinary.太粗心了!
- delphi record 内存怎么释放
delphi record 内存怎么释放 是不需要释放的,除非你使用指针方式生成的.
- HTML embed标签使用方法和属性详解
一.基本语法 代码如下: embed src=url 说明:embed可以用来插入各种多媒体,格式可以是 Midi.Wav.AIFF.AU.MP3等等,Netscape及新版的IE 都支持 ...
- MVC 无法将类型“System.Collections.Generic.List<AnonymousType#1>”隐式转换为“System.Collections.Generic.IList<Mvc3Modeltest.Models.Movie>”。存在一个显式转换(是否缺少强制转换?))
1.问题: 2.解决方案:强制指定类型. 解决之.
- Android MVC框架模式
MCV model view controller 模型-视图-控制写 M层:适合做一些业务逻辑处理,比如数据库存取操作,网络操作,复杂的算法,耗时的任务等都在model层处理. V层:应用层中处 ...
- [Javascript] Object.assign()
Best Pratices for Object.assign: http://www.cnblogs.com/Answer1215/p/5096746.html Object.assign() ca ...