【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> ...
随机推荐
- AlgorithmsI PA2: Randomized Queues and Deques Deque
本次作业考察利用array 或者linked list 实现规定时间复杂度的queue 和stack, 不能使用java 自带的stack 和queue. 目的是让我们掌握自己设计的函数的复杂度. D ...
- 字符串(KMP):BZOJ 3670 [Noi2014]动物园
3670: [Noi2014]动物园 Time Limit: 10 Sec Memory Limit: 512 MBSubmit: 1521 Solved: 813[Submit][Status] ...
- HDOJ 1846 Brave Game
Problem Description 十年前读大学的时候,中国每年都要从国外引进一些电影大片,其中有一部电影就叫<勇敢者的游戏>(英文名称:Zathura),一直到现在,我依然对于电影中 ...
- mac下的改装人生——把主硬盘换成ssd
这两天搞得最多的事情就是我的这两块硬盘,基本上的时间都被他们占用去了,但是最后的结果也是让我很开心--开机瞬秒,程序瞬秒,生活质量瞬间高了很多哈. 关于ssd的各种事情,我的另外一篇博客有讲,算是比较 ...
- SANSA 上上洛可可 贾伟作品 高山流水 香炉 香插香台香具 高端商务礼品 黑色【正品 价格 图片 折扣 评论】_尚品网ShangPin.com
SANSA 上上洛可可 贾伟作品 高山流水 香炉 香插香台香具 高端商务礼品 黑色[正品 价格 图片 折扣 评论]_尚品网ShangPin.com
- Android注解利器:ButterKnife 的基本使用
前言 ButterKnife 简介 ButterKnife是一个专注于Android系统的View注入框架,可以减少大量的findViewById以及setOnClickListener代码,可视化一 ...
- angularJS服务一
一 认识服务 1.服务这个概念其实并不陌生,在其他语言中如java便有这样的概念,其作用就是对外提供某个特定的功能,如消息服务,文件压缩服务等,是一个独立的模块.ng的服务是一个单例对象或函数,对外提 ...
- Lucene实例教程
Lucene是apache组织的一个用java实现全文搜索引擎的开源项目. 其功能非常的强大,api也很简单.总得来说用Lucene来进行建立 和搜索和操作数据库是差不多的(有点像),Document ...
- 遭遇多线程bug (1)
某些用户,机器重启后,到第三方服务器的连接起不来,而到我们自己服务器的连接就没事. 如果连接由于网络或其他原因fail掉,过一定时间后应该会重新尝试建立连接的. 测试组做初步调查,他们能在本地环境复现 ...
- POJ - 1170 Shopping Offers (五维DP)
题目大意:有一个人要买b件商品,给出每件商品的编号,价格和数量,恰逢商店打折.有s种打折方式.问怎么才干使买的价格达到最低 解题思路:最多仅仅有五种商品.且每件商品最多仅仅有5个,所以能够用5维dp来 ...