【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> ...
随机推荐
- 字符串(多串后缀自动机):HDU 4436 str2int
str2int Time Limit: 6000/3000 MS (Java/Others) Memory Limit: 131072/131072 K (Java/Others)Total S ...
- 汇编学习笔记(7)call和ret指令
ret和retf CPU执行ret指令时进行以下两步操作: (IP)=((ss)*16+(sp)) (sp)=(sp)+2 这相当于pop IP CPU执行retf指令时进行以下四步操作: (IP)= ...
- Android SDK更新失败最新解决方案
解决方案: 将https修改为http://在Android SDK manager中,的tools文件夹下,选择options...选项, 勾选 Force https//... sources t ...
- How to Implement the IContextMenu Interface
http://msdn.microsoft.com/en-us/library/windows/desktop/hh127443(v=vs.85).aspx IContextMenu is the m ...
- Nightmare(搜索)
http://acm.hdu.edu.cn/showproblem.php?pid=1072 /* 题意: 迷宫内有入口和出口 在6分钟结束后炸弹会爆炸,但是迷宫内有重置炸弹的装置,可以重置炸弹的时间 ...
- 常考的算法及Java知识总结
算法 1 字符串模式匹配问题 2 排列组合问题 3 查找排序问题 数据结构 B树(B,B*,B+,红黑树)和二叉树的区别,MAP,hashmap, JAVA: 线程sleep,wait,wake(), ...
- u盘启动openwrt
opkg update opkg install kmod-usb-ohci kmod-usb2 kmod-fs-ext3 opkg install kmod-usb-storage reboot m ...
- Android---用动画来处理布局的变化
本文译自:http://developer.android.com/training/animation/layout.html 布局动画一种系统预装的动画,每次布局配置发生变化时,系统会运行它.你所 ...
- [PWA] 16. Clean IDB
When we save items to IndexDB, we need to think about clean the items or keep those in a short list. ...
- PHP数据结构预热:PHP的迭代器(转)
迭代器有时又称光标(cursor)是程式设计的软件设计模式,可在容器物件(container,例如list或vector)上遍访的接口,设计人员无需关心容器物件的内容. 各种语言实作Iterator的 ...